﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
using System.Drawing.Imaging;
using System.IO;
namespace vnFingerPrint
{
    public class rect
    {
        public int sx, sy, width, height;
        public rect()
        {
            sx = sy = width = height = 0;
        }
        public rect(int x, int y, int rong, int cao)
        {
            sx = x;
            sy = y;
            width = rong;
            height = cao;
        }
    }
    public class matran
    {
        protected int sohang, socot;
        public bool[,] xet;
        public int Sohang
        {
            get { return this.sohang; }
        }

        public int Socot
        {
            get { return this.socot; }
        }
        public bool hople(int x, int y)
        {
            return ((x >= 0) && (x < sohang) && (y >= 0) && (y < socot));
        }
        public void xetca()
        {
            int i, j;
            xet = new bool[sohang, socot];
            for (i = 0; i < sohang; ++i)
                for (j = 0; j < socot; ++j)
                    xet[i, j] = true;
        }
        public void khongxet(rect r)
        {
            int i, j;
            for (i = r.sx; i < r.sx + r.width; i++)
                for (j = r.sy; j < r.sy + r.height; ++j)
                    if (hople(i, j)) xet[i, j] = false;
        }
    }
    public class matrannguyen : matran
    {
        public int[,] data;
        public int[,] direct;
        public matrannguyen()
        {
            sohang = socot = 0;
        }

        public matrannguyen(int sh, int sc)
        {
            sohang = sh;
            socot = sc;
            data = new int[sh, sc];
            xet = new bool[sh, sc];
            this.xetca();
        }
        public void DocBitmap(Bitmap image)
        {
            sohang = image.Width;
            socot = image.Height;
            data = new int[sohang, socot];
            BitmapData bmpData = new BitmapData();
            try
            {
                bmpData = image.LockBits(new Rectangle(0, 0, sohang, socot), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

                int remain = bmpData.Stride - bmpData.Width * 3;
                unsafe
                {
                    byte* ptr = (byte*)bmpData.Scan0;

                    for (int i = 0; i < bmpData.Height; i++)
                    {
                        for (int j = 0; j < bmpData.Width; j++)
                        {
                            if(j>=60&&j<=452)
                            {
                                data[i, j] = ptr[0] = ptr[1] = ptr[2] = (byte)((ptr[0] + ptr[1] + ptr[2]) / 3);
                            }
                            else
                            {
                                data[i, j] = 0;
                            }
                            ptr += 3;
                        }
                        ptr += remain;
                    }
                }
                image.UnlockBits(bmpData);
            }
            catch
            {
                image.UnlockBits(bmpData);
            }
            xet = new bool[Sohang, Socot];
            this.xetca();
            direct = new int[Sohang, socot];
            for(int i=0;i<Sohang;i++)
            {
                for(int j=0;j<Socot;j++)
                {
                    direct[i, j] = huongmt(i, j);
                }
            }
        }
        public Bitmap ToBitmap()
        {
            Bitmap image = new Bitmap(this.sohang, this.socot);
            BitmapData bmpData = image.LockBits(new Rectangle(0, 0, sohang, socot), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            int remain = bmpData.Stride - bmpData.Width * 3;
            unsafe
            {
                byte* ptr = (byte*)bmpData.Scan0;

                for (int i = 0; i < bmpData.Height; i++)
                {
                    for (int j = 0; j < bmpData.Width; j++)
                    {

                        ptr[0] = ptr[1] = ptr[2] = (byte)this.data[i, j];
                        ptr += 3;
                    }
                    ptr += remain;
                }
            }
            image.UnlockBits(bmpData);
            return image;
        }

        public double nhanchap1(int x, int y, matransothuc matna)
        {
            int m = matna.Sohang, n = matna.Socot;
            int p = m / 2 + m % 2;
            int q = n / 2 + n % 2;
            int i, j;
            double tg = 0;
            for (i = 0; i < m; ++i)
                for (j = 0; j < n; ++j)
                    if (hople(x + i - p, y + j - q))
                        tg += data[x + i - p, y + j - q] * matna.data[i, j];
            return tg;
        }
        public matrannguyen nhanchap(matransothuc matna)
        {
            int m = sohang, n = socot, i, j;
            matrannguyen ketqua = new matrannguyen(m, n);
            for (i = 0; i < m; ++i)
                for (j = 0; j < n; ++j)
                    ketqua.data[i, j] = (int)nhanchap1(i, j, matna);
            return ketqua;
        }
        public int trungbinh()
        {
            int i, j;
            int ketqua = 0;
            for (i = 0; i < sohang; ++i)
                for (j = 0; j < socot; ++j) ketqua += data[i, j];
            return (int)(ketqua / (sohang * socot));
        }
        public double trungbinh(rect r)
        {

            int i, j, m, n;
            m = r.sx + r.width;
            n = r.sy + r.height;
            if (m > sohang) m = sohang;
            if (n > socot) n = socot;
            double ketqua = 0;
            for (i = r.sx; i < m; ++i)
                for (j = r.sy; j < n; ++j) ketqua += data[i, j];
            ketqua /= (r.width * r.height);
            return ketqua;
        }
        public int max(rect r)
        {
            int i, j, m, n;
            int MAX;
            MAX = data[0, 0];
            m = r.sx + r.width;
            n = r.sy + r.height;
            if (m > sohang) m = sohang;
            if (n > socot) n = socot;
            for (i = r.sx; i < m; ++i)
                for (j = r.sy; j < n; ++j)
                    if (data[i, j] > MAX) MAX = data[i, j];
            return MAX;
        }
        public int min(rect r)
        {

            int i, j, m, n;
            int MIN;
            MIN = data[0, 0];
            m = r.sx + r.width;
            n = r.sy + r.height;
            if (m > sohang) m = sohang;
            if (n > socot) n = socot;
            for (i = r.sx; i < m; ++i)
                for (j = r.sy; j < n; ++j)
                    if (data[i, j] < MIN) MIN = data[i, j];
            return MIN;
        }
        public int min()
        {
            return min(new rect(0, 0, sohang, socot));
        }
        public int max()
        {
            return max(new rect(0, 0, sohang, socot));
        }
        public matrannguyen phanvung()
        {
            matrannguyen kq = new matrannguyen(512, 512);
            matrannguyen tg = new matrannguyen(32, 32);
            matrannguyen tg1 = new matrannguyen(32, 32);
            for (int i = 0; i < 32; ++i)
                for (int j = 0; j < 32; ++j)
                {
                    int bien = 0;
                    for (int k = 0; k < 16; ++k)
                        for (int l = 0; l < 16; ++l)
                        {
                            bien += data[16 * i + k, 16 * j + l];
                        }
                    bien = (int)bien / (16 * 16);
                    tg.data[i, j] = bien;
                }
            for (int i = 0; i < 32; ++i)
                for (int j = 0; j < 32; ++j)
                {
                    int xet = 0;
                    for (int k = 0; k < 16; ++k)
                        for (int l = 0; l < 16; ++l)
                        {
                            xet += (int)(data[16 * i + k, 16 * j + l] - tg.data[i, j]) * (data[16 * i + k, 16 * j + l] - tg.data[i, j]);
                        }
                    tg1.data[i, j] = (int)xet / (16 * 16);
                }
            matrannhiphan tg3 = new matrannhiphan(32, 32);
            for (int i = 0; i < 32; ++i)
                for (int j = 0; j < 32; ++j)
                {
                    tg3.data[i, j] = (tg1.data[i, j] > 40);
                }
            tg3 = tg3.co();
            tg3 = tg3.co();
            //tg3 = tg3.co();
            //tg3 = tg3.co();
            //tg3 = tg3.gian();
            //tg3 = tg3.gian();
            tg3 = tg3.gian();
            tg3 = tg3.gian();
            matrannhiphan tg4 = tg3.tachbien();
            for (int i = 0; i < 32; ++i)
                for (int j = 0; j < 32; ++j)
                {
                    for (int k = 0; k < 16; ++k)
                        for (int l = 0; l < 16; ++l)
                        {
                            if (!tg3.data[i, j])
                                kq.data[16 * i + k, 16 * j + l] = 255;
                            else
                                kq.data[16 * i + k, 16 * j + l] = 0;

                        }
                }
            int ng;
            for (int i = 0; i < 32; ++i)
                for (int j = 0; j < 32; ++j)
                    if (tg4.data[i, j])
                    {
                        ng = (int)(max(new rect(16 * i, 16 * j, 16, 16)) + min(new rect(16 * i, 16 * j, 16, 16))) / 2;
                        for (int k = 0; k < 16; ++k)
                            for (int l = 0; l < 16; ++l)
                            {
                                if (data[16 * i + k, 16 * j + l] > ng + 10)
                                    kq.data[16 * i + k, 16 * j + l] = 255;
                                else
                                    kq.data[16 * i + k, 16 * j + l] = 0;
                            }
                    }
            return kq;
        }
        public matrannguyen chonnguong()
        {
            int tg;
            matrannguyen ketqua = new matrannguyen(32, 32);
            for (int i = 0; i < 32; ++i)
                for (int j = 0; j < 32; ++j)
                {
                    tg = 0;
                    for (int k = 0; k < 16; ++k)
                        for (int l = 0; l < 16; ++l)
                        {
                            tg += data[16 * i + k, 16 * j + l];
                        }
                    ketqua.data[i, j] = tg;
                    ketqua.data[i, j] = (int)(ketqua.data[i, j] / (16 * 16));
                }
            return ketqua;
        }
        public matrannguyen nhiphan()
        {
            matrannguyen kq = new matrannguyen(sohang, socot);
            matrannguyen tg = new matrannguyen(32, 32);
            int trunggian;
            tg = chonnguong();
            for (int i = 0; i < 32; ++i)
                for (int j = 0; j < 32; ++j)
                {
                    trunggian = tg.data[i, j];
                    for (int k = 0; k < 16; ++k)
                        for (int l = 0; l < 16; ++l)
                        {
                            if (data[16 * i + k, 16 * j + l] >= trunggian)
                                kq.data[16 * i + k, 16 * j + l] = 255;
                            else
                                kq.data[16 * i + k, 16 * j + l] = 0;
                        }

                }
            return kq;
        }
        public matrannguyen mthuongmn(int w)
        {
            matrannguyen kq = new matrannguyen(sohang / w, socot / w);
            matrannguyen kq1 = new matrannguyen(sohang, socot);
            int tg;
            for (int k = 0; k < kq.Sohang; ++k)
                for (int l = 0; l < kq.Socot; ++l)
                {
                    int max = 0;
                    int xet = 0;
                    int[] dem = new int[8];
                    dem = ganvt();
                    for (int i = 0; i < w; ++i)
                        for (int j = 0; j < w; ++j)
                        {
                            tg = huongmt(16 * k + i, 16 * l + j);
                            if (tg == 0) dem[0]++;
                            if (tg == 1) dem[1]++;
                            if (tg == 2) dem[2]++;
                            if (tg == 3) dem[3]++;
                            if (tg == 4) dem[4]++;
                            if (tg == 5) dem[5]++;
                            if (tg == 6) dem[6]++;
                            if (tg == 7) dem[7]++;
                        }
                    for (int n = 0; n < 8; n++)
                    {
                        if (max < dem[n])
                        {
                            max = dem[n];
                            xet = n;
                        }
                    }
                    kq.data[k, l] = xet;
                }
            for (int k = 0; k < 32; ++k)
                for (int l = 0; l < 32; ++l)
                {
                    for (int i = 0; i < 16; ++i)
                        for (int j = 0; j < 16; ++j)
                        {
                            kq1.data[16 * k + i, 16 * l + j] = kq.data[k, l];
                        }
                }
            return kq1;
        }
        public int[] ganvt()
        {
            int[] kq = new int[8];
            for (int i = 0; i < 8; i++)
                kq[i] = 0;
            return kq;
        }
        public int huongmt(int i, int j)
        {
            int kq;
            int[] tg = new int[8];
            int[] tg1 = new int[4];
            if ((i - 4 > 0) && (j - 4 > 0) && (i + 4 < sohang) && (j + 4 < socot))
            {
                tg[0] = (int)(data[i, j - 4] + data[i, j - 2] + data[i, j + 2] + data[i, j + 4]) / 4;
                tg[1] = (int)(data[i - 2, j - 4] + data[i - 1, j - 2] + data[i + 1, j + 2] + data[i + 2, j + 4]) / 4;
                tg[2] = (int)(data[i - 4, j - 4] + data[i - 2, j - 2] + data[i + 2, j + 2] + data[i + 4, j + 4]) / 4;
                tg[3] = (int)(data[i - 4, j - 2] + data[i - 2, j - 1] + data[i + 2, j + 1] + data[i + 4, j + 2]) / 4;
                tg[4] = (int)(data[i - 4, j] + data[i - 2, j] + data[i + 2, j] + data[i + 4, j]) / 4;
                tg[5] = (int)(data[i - 2, j + 1] + data[i - 4, j + 2] + data[i + 2, j - 1] + data[i + 4, j - 2]) / 4;
                tg[6] = (int)(data[i + 4, j - 4] + data[i + 2, j - 2] + data[i - 2, j + 2] + data[i - 2, j + 4]) / 4;
                tg[7] = (int)(data[i + 2, j - 4] + data[i + 1, j - 2] + data[i - 1, j + 2] + data[i - 2, j + 4]) / 4;
            }
            for (int k = 0; k < 4; k++)
            {
                tg1[k] = Math.Abs(tg[k] - tg[k + 4]);
            }
            int max = tg1[0];
            int dem = 0;
            for (int l = 1; l < 4; l++)
            {
                if (max < tg1[l])
                {
                    max = tg1[l];
                    dem = l;
                }
            }
            if (Math.Abs(data[i, j] - tg[dem]) < Math.Abs(data[i, j] - tg[dem + 4]))
                kq = dem;
            else kq = dem + 4;
            return kq;
        }

        public matrannguyen gabor()
        {
            // ma tran he so cho huong 0 rad
            matransothuc s1 = new matransothuc(11, 11);
            s1.data[0, 0] = -0.20961; s1.data[0, 1] = -0.27769; s1.data[0, 2] = -0.34559; s1.data[0, 3] = -0.40404; s1.data[0, 4] = -0.44375; s1.data[0, 5] = -0.45783; s1.data[0, 6] = -0.44375; s1.data[0, 7] = -0.40404; s1.data[0, 8] = -0.34559; s1.data[0, 9] = -0.27769; s1.data[0, 10] = -0.20961;
            s1.data[1, 0] = -0.22466; s1.data[1, 1] = -0.29762; s1.data[1, 2] = -0.37039; s1.data[1, 3] = -0.43304; s1.data[1, 4] = -0.47560; s1.data[1, 5] = -0.49069; s1.data[1, 6] = -0.47560; s1.data[1, 7] = -0.43304; s1.data[1, 8] = -0.37039; s1.data[1, 9] = -0.29762; s1.data[1, 10] = -0.22466;
            s1.data[2, 0] = -0.10679; s1.data[2, 1] = -0.14148; s1.data[2, 2] = -0.17607; s1.data[2, 3] = -0.20585; s1.data[2, 4] = -0.22608; s1.data[2, 5] = -0.23326; s1.data[2, 6] = -0.22608; s1.data[2, 7] = -0.20585; s1.data[2, 8] = -0.17607; s1.data[2, 9] = -0.14148; s1.data[2, 10] = -0.10679;
            s1.data[3, 0] = 0.12485; s1.data[3, 1] = 0.16540; s1.data[3, 2] = 0.20585; s1.data[3, 3] = 0.24066; s1.data[3, 4] = 0.26432; s1.data[3, 5] = 0.27271; s1.data[3, 6] = 0.26432; s1.data[3, 7] = 0.24066; s1.data[3, 8] = 0.20585; s1.data[3, 9] = 0.16540; s1.data[3, 10] = 0.12485;
            s1.data[4, 0] = 0.35900; s1.data[4, 1] = 0.47560; s1.data[4, 2] = 0.59189; s1.data[4, 3] = 0.69199; s1.data[4, 4] = 0.76000; s1.data[4, 5] = 0.78413; s1.data[4, 6] = 0.76000; s1.data[4, 7] = 0.69199; s1.data[4, 8] = 0.59189; s1.data[4, 9] = 0.47560; s1.data[4, 10] = 0.35900;
            s1.data[5, 0] = 0.45783; s1.data[5, 1] = 0.60653; s1.data[5, 2] = 0.75484; s1.data[5, 3] = 0.88250; s1.data[5, 4] = 0.96923; s1.data[5, 5] = 1.00000; s1.data[5, 6] = 0.96923; s1.data[5, 7] = 0.88250; s1.data[5, 8] = 0.75484; s1.data[5, 9] = 0.60653; s1.data[5, 10] = 0.45783;
            s1.data[6, 0] = 0.35900; s1.data[6, 1] = 0.47560; s1.data[6, 2] = 0.59189; s1.data[6, 3] = 0.69199; s1.data[6, 4] = 0.76000; s1.data[6, 5] = 0.78413; s1.data[6, 6] = 0.76000; s1.data[6, 7] = 0.69199; s1.data[6, 8] = 0.59189; s1.data[6, 9] = 0.47560; s1.data[6, 10] = 0.35900;
            s1.data[7, 0] = 0.12485; s1.data[7, 1] = 0.16540; s1.data[7, 2] = 0.20585; s1.data[7, 3] = 0.24066; s1.data[7, 4] = 0.26432; s1.data[7, 5] = 0.27271; s1.data[7, 6] = 0.26432; s1.data[7, 7] = 0.24066; s1.data[7, 8] = 0.20585; s1.data[7, 9] = 0.16540; s1.data[7, 10] = 0.12485;
            s1.data[8, 0] = -0.10679; s1.data[8, 1] = -0.14148; s1.data[8, 2] = -0.17607; s1.data[8, 3] = -0.20585; s1.data[8, 4] = -0.22608; s1.data[8, 5] = -0.23326; s1.data[8, 6] = -0.22608; s1.data[8, 7] = -0.20585; s1.data[8, 8] = -0.17607; s1.data[8, 9] = -0.14148; s1.data[8, 10] = -0.10679;
            s1.data[9, 0] = -0.22466; s1.data[9, 1] = -0.29762; s1.data[9, 2] = -0.37039; s1.data[9, 3] = -0.43304; s1.data[9, 4] = -0.47560; s1.data[9, 5] = -0.49069; s1.data[9, 6] = -0.47560; s1.data[9, 7] = -0.43304; s1.data[9, 8] = -0.37039; s1.data[9, 9] = -0.29762; s1.data[9, 10] = -0.22466;
            s1.data[10, 0] = -0.20961; s1.data[10, 1] = -0.27769; s1.data[10, 2] = -0.34559; s1.data[10, 3] = -0.40404; s1.data[10, 4] = -0.44375; s1.data[10, 5] = -0.45783; s1.data[10, 6] = -0.44375; s1.data[10, 7] = -0.40404; s1.data[10, 8] = -0.34559; s1.data[10, 9] = -0.27769; s1.data[10, 10] = -0.20961;

            // ma tran he so cho huong pi/8 rad
            matransothuc s2 = new matransothuc(11, 11);

            s2.data[0, 0] = -0.02705; s2.data[0, 1] = -0.10038; s2.data[0, 2] = -0.19807; s2.data[0, 3] = -0.30375; s2.data[0, 4] = -0.39369; s2.data[0, 5] = -0.44480; s2.data[0, 6] = -0.44375; s2.data[0, 7] = -0.39229; s2.data[0, 8] = -0.30619; s2.data[0, 9] = -0.20282; s2.data[0, 10] = -0.11968;
            s2.data[1, 0] = 0.12105; s2.data[1, 1] = 0.07691; s2.data[1, 2] = -0.01365; s2.data[1, 3] = -0.14291; s2.data[1, 4] = -0.28735; s2.data[1, 5] = -0.41395; s2.data[1, 6] = -0.49199; s2.data[1, 7] = -0.50485; s2.data[1, 8] = -0.45562; s2.data[1, 9] = -0.36417; s2.data[1, 10] = -0.25761;
            s2.data[2, 0] = 0.29655; s2.data[2, 1] = 0.32558; s2.data[2, 2] = 0.29814; s2.data[2, 3] = 0.20355; s2.data[2, 4] = 0.05100; s2.data[2, 5] = -0.12821; s2.data[2, 6] = -0.29238; s2.data[2, 7] = -0.40397; s2.data[2, 8] = -0.44348; s2.data[2, 9] = -0.41455; s2.data[2, 10] = -0.33885;
            s2.data[3, 0] = 0.40369; s2.data[3, 1] = 0.52468; s2.data[3, 2] = 0.60280; s2.data[3, 3] = 0.60553; s2.data[3, 4] = 0.51782; s2.data[3, 5] = 0.35162; s2.data[3, 6] = 0.14418; s2.data[3, 7] = -0.05531; s2.data[3, 8] = -0.20418; s2.data[3, 9] = -0.28067; s2.data[3, 10] = -0.28770;
            s2.data[4, 0] = 0.36071; s2.data[4, 1] = 0.54565; s2.data[4, 2] = 0.72437; s2.data[4, 3] = 0.85111; s2.data[4, 4] = 0.88562; s2.data[4, 5] = 0.81047; s2.data[4, 6] = 0.64024; s2.data[4, 7] = 0.41712; s2.data[4, 8] = 0.19441; s2.data[4, 9] = 0.01676; s2.data[4, 10] = -0.09334;
            s2.data[5, 0] = 0.16495; s2.data[5, 1] = 0.34697; s2.data[5, 2] = 0.56682; s2.data[5, 3] = 0.78241; s2.data[5, 4] = 0.94135; s2.data[5, 5] = 1.00000; s2.data[5, 6] = 0.94135; s2.data[5, 7] = 0.78241; s2.data[5, 8] = 0.56682; s2.data[5, 9] = 0.34697; s2.data[5, 10] = 0.16495;
            s2.data[6, 0] = -0.09334; s2.data[6, 1] = 0.01676; s2.data[6, 2] = 0.19441; s2.data[6, 3] = 0.41712; s2.data[6, 4] = 0.64024; s2.data[6, 5] = 0.81047; s2.data[6, 6] = 0.88562; s2.data[6, 7] = 0.85111; s2.data[6, 8] = 0.72437; s2.data[6, 9] = 0.54565; s2.data[6, 10] = 0.36071;
            s2.data[7, 0] = -0.28770; s2.data[7, 1] = -0.28067; s2.data[7, 2] = -0.20418; s2.data[7, 3] = -0.05531; s2.data[7, 4] = 0.14418; s2.data[7, 5] = 0.35162; s2.data[7, 6] = 0.51782; s2.data[7, 7] = 0.60553; s2.data[7, 8] = 0.60280; s2.data[7, 9] = 0.52468; s2.data[7, 10] = 0.40369;
            s2.data[8, 0] = -0.33885; s2.data[8, 1] = -0.41455; s2.data[8, 2] = -0.44348; s2.data[8, 3] = -0.40397; s2.data[8, 4] = -0.29238; s2.data[8, 5] = -0.12821; s2.data[8, 6] = 0.05100; s2.data[8, 7] = 0.20355; s2.data[8, 8] = 0.29814; s2.data[8, 9] = 0.32558; s2.data[8, 10] = 0.29655;
            s2.data[9, 0] = -0.25761; s2.data[9, 1] = -0.36417; s2.data[9, 2] = -0.45562; s2.data[9, 3] = -0.50485; s2.data[9, 4] = -0.49199; s2.data[9, 5] = -0.41395; s2.data[9, 6] = -0.28735; s2.data[9, 7] = -0.14291; s2.data[9, 8] = -0.01365; s2.data[9, 9] = 0.07691; s2.data[9, 10] = 0.12105;
            s2.data[10, 0] = -0.11968; s2.data[10, 1] = -0.20828; s2.data[10, 2] = -0.30619; s2.data[10, 3] = -0.39229; s2.data[10, 4] = -0.44375; s2.data[10, 5] = -0.44480; s2.data[10, 6] = -0.39369; s2.data[10, 7] = -0.30375; s2.data[10, 8] = -0.19807; s2.data[10, 9] = -0.10038; s2.data[10, 10] = -0.02705;

            // ma tran he so cho huong 2pi/8 rad
            matransothuc s3 = new matransothuc(11, 11);
            s3.data[0, 0] = 0.20961; s3.data[0, 1] = 0.25073; s3.data[0, 2] = 0.21790; s3.data[0, 3] = 0.09523; s3.data[0, 4] = -0.09092; s3.data[0, 5] = -0.27731; s3.data[0, 6] = -0.39445; s3.data[0, 7] = -0.40384; s3.data[0, 8] = -0.31657; s3.data[0, 9] = -0.18181; s3.data[0, 10] = -0.05581;
            s3.data[1, 0] = 0.25073; s3.data[1, 1] = 0.36788; s3.data[1, 2] = 0.41339; s3.data[1, 3] = 0.33749; s3.data[1, 4] = 0.13856; s3.data[1, 5] = -0.12428; s3.data[1, 6] = -0.35607; s3.data[1, 7] = -0.47579; s3.data[1, 8] = -0.45761; s3.data[1, 9] = -0.33699; s3.data[1, 10] = -0.18181;
            s3.data[2, 0] = 0.21790; s3.data[2, 1] = 0.41339; s3.data[2, 2] = 0.56978; s3.data[2, 3] = 0.60147; s3.data[2, 4] = 0.46130; s3.data[2, 5] = 0.17791; s3.data[2, 6] = -0.14990; s3.data[2, 7] = -0.40348; s3.data[2, 8] = -0.50648; s3.data[2, 9] = -0.45761; s3.data[2, 10] = -0.31657;
            s3.data[3, 0] = 0.09523; s3.data[3, 1] = 0.33749; s3.data[3, 2] = 0.60147; s3.data[3, 3] = 0.77880; s3.data[3, 4] = 0.77231; s3.data[3, 5] = 0.55643; s3.data[3, 6] = 0.20160; s3.data[3, 7] = -0.15957; s3.data[3, 8] = -0.40348; s3.data[3, 9] = -0.47579; s3.data[3, 10] = -0.40384;
            s3.data[4, 0] = -0.09092; s3.data[4, 1] = 0.13856; s3.data[4, 2] = 0.46130; s3.data[4, 3] = 0.77231; s3.data[4, 4] = 0.93941; s3.data[4, 5] = 0.87514; s3.data[4, 6] = 0.59232; s3.data[4, 7] = 0.20160; s3.data[4, 8] = -0.14990; s3.data[4, 9] = -0.35607; s3.data[4, 10] = -0.39445;
            s3.data[5, 0] = -0.27731; s3.data[5, 1] = -0.12428; s3.data[5, 2] = 0.17791; s3.data[5, 3] = 0.55643; s3.data[5, 4] = 0.87514; s3.data[5, 5] = 1.00000; s3.data[5, 6] = 0.87514; s3.data[5, 7] = 0.55643; s3.data[5, 8] = 0.17791; s3.data[5, 9] = -0.12428; s3.data[5, 10] = -0.27731;
            s3.data[6, 0] = -0.39445; s3.data[6, 1] = -0.35607; s3.data[6, 2] = -0.14990; s3.data[6, 3] = 0.20160; s3.data[6, 4] = 0.59232; s3.data[6, 5] = 0.87514; s3.data[6, 6] = 0.93941; s3.data[6, 7] = 0.77231; s3.data[6, 8] = 0.46130; s3.data[6, 9] = 0.13856; s3.data[6, 10] = -0.09092;
            s3.data[7, 0] = -0.40384; s3.data[7, 1] = -0.47579; s3.data[7, 2] = -0.40348; s3.data[7, 3] = -0.15957; s3.data[7, 4] = 0.20160; s3.data[7, 5] = 0.55643; s3.data[7, 6] = 0.77231; s3.data[7, 7] = 0.77880; s3.data[7, 8] = 0.60147; s3.data[7, 9] = 0.33749; s3.data[7, 10] = 0.09523;
            s3.data[8, 0] = -0.31657; s3.data[8, 1] = -0.45761; s3.data[8, 2] = -0.50648; s3.data[8, 3] = -0.40348; s3.data[8, 4] = -0.14990; s3.data[8, 5] = 0.17791; s3.data[8, 6] = 0.46130; s3.data[8, 7] = 0.60147; s3.data[8, 8] = 0.56978; s3.data[8, 9] = 0.41339; s3.data[8, 10] = 0.21790;
            s3.data[9, 0] = -0.18181; s3.data[9, 1] = -0.33699; s3.data[9, 2] = -0.45761; s3.data[9, 3] = -0.47579; s3.data[9, 4] = -0.35607; s3.data[9, 5] = -0.12428; s3.data[9, 6] = 0.13856; s3.data[9, 7] = 0.33749; s3.data[9, 8] = 0.41339; s3.data[9, 9] = 0.36788; s3.data[9, 10] = 0.25073;
            s3.data[10, 0] = -0.05581; s3.data[10, 1] = -0.18181; s3.data[10, 2] = -0.31657; s3.data[10, 3] = -0.40348; s3.data[10, 4] = -0.39445; s3.data[10, 5] = -0.27731; s3.data[10, 6] = -0.09092; s3.data[10, 7] = 0.09523; s3.data[10, 8] = 0.21790; s3.data[10, 9] = 0.25073; s3.data[10, 10] = 0.20961;

            // ma tran he so cho huong 3pi/8 rad
            matransothuc s4 = new matransothuc(11, 11);
            s4.data[0, 0] = -0.02705; s4.data[0, 1] = 0.12105; s4.data[0, 2] = 0.29655; s4.data[0, 3] = 0.40369; s4.data[0, 4] = 0.36071; s4.data[0, 5] = 0.16495; s4.data[0, 6] = -0.09334; s4.data[0, 7] = -0.28770; s4.data[0, 8] = -0.33885; s4.data[0, 9] = -0.25761; s4.data[0, 10] = -0.11968;
            s4.data[1, 0] = -0.10038; s4.data[1, 1] = 0.07691; s4.data[1, 2] = 0.32558; s4.data[1, 3] = 0.52468; s4.data[1, 4] = 0.54565; s4.data[1, 5] = 0.34697; s4.data[1, 6] = 0.01676; s4.data[1, 7] = -0.28067; s4.data[1, 8] = -0.41455; s4.data[1, 9] = -0.36417; s4.data[1, 10] = -0.20828;
            s4.data[2, 0] = -0.19807; s4.data[2, 1] = -0.01365; s4.data[2, 2] = 0.29814; s4.data[2, 3] = 0.60280; s4.data[2, 4] = 0.72437; s4.data[2, 5] = 0.56682; s4.data[2, 6] = 0.19441; s4.data[2, 7] = -0.20418; s4.data[2, 8] = -0.44348; s4.data[2, 9] = -0.45562; s4.data[2, 10] = -0.30619;
            s4.data[3, 0] = -0.30375; s4.data[3, 1] = -0.14291; s4.data[3, 2] = 0.20335; s4.data[3, 3] = 0.60553; s4.data[3, 4] = 0.85111; s4.data[3, 5] = 0.78241; s4.data[3, 6] = 0.41712; s4.data[3, 7] = -0.05531; s4.data[3, 8] = -0.40397; s4.data[3, 9] = -0.50485; s4.data[3, 10] = -0.39229;
            s4.data[4, 0] = -0.39369; s4.data[4, 1] = -0.28735; s4.data[4, 2] = 0.05100; s4.data[4, 3] = 0.51782; s4.data[4, 4] = 0.88562; s4.data[4, 5] = 0.94135; s4.data[4, 6] = 0.64024; s4.data[4, 7] = 0.14418; s4.data[4, 8] = -0.29238; s4.data[4, 9] = -0.49199; s4.data[4, 10] = -0.44375;
            s4.data[5, 0] = -0.44480; s4.data[5, 1] = -0.41395; s4.data[5, 2] = -0.12821; s4.data[5, 3] = 0.35162; s4.data[5, 4] = 0.81047; s4.data[5, 5] = 1.00000; s4.data[5, 6] = 0.81047; s4.data[5, 7] = 0.35162; s4.data[5, 8] = -0.12821; s4.data[5, 9] = -0.41395; s4.data[5, 10] = -0.44480;
            s4.data[6, 0] = -0.44375; s4.data[6, 1] = -0.49199; s4.data[6, 2] = -0.29238; s4.data[6, 3] = 0.14418; s4.data[6, 4] = 0.64024; s4.data[6, 5] = 0.94135; s4.data[6, 6] = 0.88562; s4.data[6, 7] = 0.51782; s4.data[6, 8] = 0.05100; s4.data[6, 9] = -0.28735; s4.data[6, 10] = -0.39369;
            s4.data[7, 0] = -0.39229; s4.data[7, 1] = -0.50485; s4.data[7, 2] = -0.40397; s4.data[7, 3] = -0.05531; s4.data[7, 4] = 0.41712; s4.data[7, 5] = 0.78241; s4.data[7, 6] = 0.85111; s4.data[7, 7] = 0.60553; s4.data[7, 8] = 0.20335; s4.data[7, 9] = -0.14291; s4.data[7, 10] = -0.30375;
            s4.data[8, 0] = -0.30619; s4.data[8, 1] = -0.45562; s4.data[8, 2] = -0.44348; s4.data[8, 3] = -0.20418; s4.data[8, 4] = 0.19441; s4.data[8, 5] = 0.56682; s4.data[8, 6] = 0.72437; s4.data[8, 7] = 0.60280; s4.data[8, 8] = 0.29814; s4.data[8, 9] = -0.01365; s4.data[8, 10] = -0.19807;
            s4.data[9, 0] = -0.20828; s4.data[9, 1] = -0.36417; s4.data[9, 2] = -0.41455; s4.data[9, 3] = -0.28067; s4.data[9, 4] = 0.01676; s4.data[9, 5] = 0.34697; s4.data[9, 6] = 0.54565; s4.data[9, 7] = 0.52468; s4.data[9, 8] = 0.32558; s4.data[9, 9] = 0.07691; s4.data[9, 10] = -0.10038;
            s4.data[10, 0] = -0.11968; s4.data[10, 1] = -0.25761; s4.data[10, 2] = -0.33885; s4.data[10, 3] = -0.28770; s4.data[10, 4] = -0.09334; s4.data[10, 5] = 0.16495; s4.data[10, 6] = 0.36071; s4.data[10, 7] = 0.40369; s4.data[10, 8] = 0.29655; s4.data[10, 9] = 0.12105; s4.data[10, 10] = -0.02705;

            // ma tran he so cho huong 4pi/8 rad
            matransothuc s5 = new matransothuc(11, 11);
            s5.data[0, 0] = -0.20961; s5.data[0, 1] = -0.22466; s5.data[0, 2] = -0.10679; s5.data[0, 3] = 0.12485; s5.data[0, 4] = 0.35900; s5.data[0, 5] = 0.45783; s5.data[0, 6] = 0.35900; s5.data[0, 7] = 0.12485; s5.data[0, 8] = -0.10679; s5.data[0, 9] = -0.22466; s5.data[0, 10] = -0.20961;
            s5.data[1, 0] = -0.27769; s5.data[1, 1] = -0.29762; s5.data[1, 2] = -0.14148; s5.data[1, 3] = 0.16540; s5.data[1, 4] = 0.47560; s5.data[1, 5] = 0.60653; s5.data[1, 6] = 0.47560; s5.data[1, 7] = 0.16540; s5.data[1, 8] = -0.14148; s5.data[1, 9] = -0.29762; s5.data[1, 10] = -0.27769;
            s5.data[2, 0] = -0.34559; s5.data[2, 1] = -0.37039; s5.data[2, 2] = -0.17607; s5.data[2, 3] = 0.20585; s5.data[2, 4] = 0.59189; s5.data[2, 5] = 0.75484; s5.data[2, 6] = 0.59189; s5.data[2, 7] = 0.20585; s5.data[2, 8] = -0.17607; s5.data[2, 9] = -0.37039; s5.data[2, 10] = -0.34559;
            s5.data[3, 0] = -0.40404; s5.data[3, 1] = -0.43304; s5.data[3, 2] = -0.20585; s5.data[3, 3] = 0.24066; s5.data[3, 4] = 0.69199; s5.data[3, 5] = 0.88250; s5.data[3, 6] = 0.69199; s5.data[3, 7] = 0.24066; s5.data[3, 8] = -0.20585; s5.data[3, 9] = -0.43304; s5.data[3, 10] = -0.40404;
            s5.data[4, 0] = -0.44375; s5.data[4, 1] = -0.47560; s5.data[4, 2] = -0.22608; s5.data[4, 3] = 0.26432; s5.data[4, 4] = 0.76000; s5.data[4, 5] = 0.96923; s5.data[4, 6] = 0.76000; s5.data[4, 7] = 0.26432; s5.data[4, 8] = -0.22608; s5.data[4, 9] = -0.47560; s5.data[4, 10] = -0.44375;
            s5.data[5, 0] = -0.45783; s5.data[5, 1] = -0.49069; s5.data[5, 2] = -0.23326; s5.data[5, 3] = 0.27271; s5.data[5, 4] = 0.78413; s5.data[5, 5] = 1.00000; s5.data[5, 6] = 0.78413; s5.data[5, 7] = 0.27271; s5.data[5, 8] = -0.23326; s5.data[5, 9] = -0.49069; s5.data[5, 10] = -0.45783;
            s5.data[6, 0] = -0.44375; s5.data[6, 1] = -0.47560; s5.data[6, 2] = -0.22608; s5.data[6, 3] = 0.26432; s5.data[6, 4] = 0.76000; s5.data[6, 5] = 0.96923; s5.data[6, 6] = 0.76000; s5.data[6, 7] = 0.26432; s5.data[6, 8] = -0.22608; s5.data[6, 9] = -0.47560; s5.data[6, 10] = -0.44375;
            s5.data[7, 0] = -0.40404; s5.data[7, 1] = -0.43304; s5.data[7, 2] = -0.20585; s5.data[7, 3] = 0.24066; s5.data[7, 4] = 0.69199; s5.data[7, 5] = 0.88250; s5.data[7, 6] = 0.69199; s5.data[7, 7] = 0.24066; s5.data[7, 8] = -0.20585; s5.data[7, 9] = -0.43304; s5.data[7, 10] = -0.40404;
            s5.data[8, 0] = -0.34559; s5.data[8, 1] = -0.37039; s5.data[8, 2] = -0.17607; s5.data[8, 3] = 0.20585; s5.data[8, 4] = 0.59189; s5.data[8, 5] = 0.75484; s5.data[8, 6] = 0.59189; s5.data[8, 7] = 0.20585; s5.data[8, 8] = -0.17607; s5.data[8, 9] = -0.37039; s5.data[8, 10] = -0.34559;
            s5.data[9, 0] = -0.27769; s5.data[9, 1] = -0.29762; s5.data[9, 2] = -0.14148; s5.data[9, 3] = 0.16540; s5.data[9, 4] = 0.47560; s5.data[9, 5] = 0.60653; s5.data[9, 6] = 0.47560; s5.data[9, 7] = 0.16540; s5.data[9, 8] = -0.14148; s5.data[9, 9] = -0.29762; s5.data[9, 10] = -0.27769;
            s5.data[10, 0] = -0.20961; s5.data[10, 1] = -0.22466; s5.data[10, 2] = -0.10679; s5.data[10, 3] = 0.12485; s5.data[10, 4] = 0.35900; s5.data[10, 5] = 0.45783; s5.data[10, 6] = 0.35900; s5.data[10, 7] = 0.12485; s5.data[10, 8] = -0.10679; s5.data[10, 9] = 0.22466; s5.data[10, 10] = -0.20961;

            // ma tran he so cho huong 5pi/8 rad
            matransothuc s6 = new matransothuc(11, 11);
            s6.data[0, 0] = -0.11968; s6.data[0, 1] = -0.25761; s6.data[0, 2] = -0.33885; s6.data[0, 3] = -0.28770; s6.data[0, 4] = -0.09334; s6.data[0, 5] = 0.16495; s6.data[0, 6] = 0.36071; s6.data[0, 7] = 0.40369; s6.data[0, 8] = 0.29655; s6.data[0, 9] = 0.12105; s6.data[0, 10] = -0.02705;
            s6.data[1, 0] = -0.20828; s6.data[1, 1] = -0.36417; s6.data[1, 2] = -0.41455; s6.data[1, 3] = -0.28067; s6.data[1, 4] = 0.01676; s6.data[1, 5] = 0.34697; s6.data[1, 6] = 0.54565; s6.data[1, 7] = 0.52468; s6.data[1, 8] = 0.32558; s6.data[1, 9] = 0.07691; s6.data[1, 10] = -0.10038;
            s6.data[2, 0] = -0.30619; s6.data[2, 1] = -0.45562; s6.data[2, 2] = -0.44348; s6.data[2, 3] = -0.20418; s6.data[2, 4] = 0.19441; s6.data[2, 5] = 0.56682; s6.data[2, 6] = 0.72437; s6.data[2, 7] = 0.60280; s6.data[2, 8] = 0.29814; s6.data[2, 9] = -0.01365; s6.data[2, 10] = -0.19807;
            s6.data[3, 0] = -0.39229; s6.data[3, 1] = -0.50485; s6.data[3, 2] = -0.40397; s6.data[3, 3] = -0.05531; s6.data[3, 4] = 0.41712; s6.data[3, 5] = 0.78241; s6.data[3, 6] = 0.85111; s6.data[3, 7] = 0.60553; s6.data[3, 8] = 0.20335; s6.data[3, 9] = -0.14291; s6.data[3, 10] = -0.30375;
            s6.data[4, 0] = -0.44375; s6.data[4, 1] = -0.49199; s6.data[4, 2] = -0.29238; s6.data[4, 3] = 0.14418; s6.data[4, 4] = 0.64024; s6.data[4, 5] = 0.94135; s6.data[4, 6] = 0.88562; s6.data[4, 7] = 0.51782; s6.data[4, 8] = 0.05100; s6.data[4, 9] = -0.28735; s6.data[4, 10] = -0.39369;
            s6.data[5, 0] = -0.44480; s6.data[5, 1] = -0.41395; s6.data[5, 2] = -0.12821; s6.data[5, 3] = 0.35162; s6.data[5, 4] = 0.81047; s6.data[5, 5] = 1.00000; s6.data[5, 6] = 0.81047; s6.data[5, 7] = 0.35162; s6.data[5, 8] = -0.12821; s6.data[5, 9] = -0.41395; s6.data[5, 10] = -0.44480;
            s6.data[6, 0] = -0.39369; s6.data[6, 1] = -0.28735; s6.data[6, 2] = 0.05100; s6.data[6, 3] = 0.51782; s6.data[6, 4] = 0.88562; s6.data[6, 5] = 0.94135; s6.data[6, 6] = 0.64024; s6.data[6, 7] = 0.14418; s6.data[6, 8] = -0.29238; s6.data[6, 9] = -0.49199; s6.data[6, 10] = -0.44375;
            s6.data[7, 0] = -0.30375; s6.data[7, 1] = -0.14291; s6.data[7, 2] = 0.20335; s6.data[7, 3] = 0.60553; s6.data[7, 4] = 0.85111; s6.data[7, 5] = 0.78241; s6.data[7, 6] = 0.41712; s6.data[7, 7] = -0.05531; s6.data[7, 8] = -0.40397; s6.data[7, 9] = -0.50485; s6.data[7, 10] = -0.39229;
            s6.data[8, 0] = -0.19807; s6.data[8, 1] = -0.01365; s6.data[8, 2] = 0.29814; s6.data[8, 3] = 0.60280; s6.data[8, 4] = 0.72437; s6.data[8, 5] = 0.56682; s6.data[8, 6] = 0.19441; s6.data[8, 7] = -0.20418; s6.data[8, 8] = -0.44348; s6.data[8, 9] = -0.45562; s6.data[8, 10] = -0.30619;
            s6.data[9, 0] = -0.10083; s6.data[9, 1] = 0.07691; s6.data[9, 2] = 0.32558; s6.data[9, 3] = 0.52468; s6.data[9, 4] = 0.54565; s6.data[9, 5] = 0.34697; s6.data[9, 6] = 0.01676; s6.data[9, 7] = -0.28067; s6.data[9, 8] = -0.41455; s6.data[9, 9] = -0.36417; s6.data[9, 10] = -0.20828;
            s6.data[10, 0] = -0.02705; s6.data[10, 1] = 0.012105; s6.data[10, 2] = 0.29655; s6.data[10, 3] = 0.40369; s6.data[10, 4] = 0.36071; s6.data[10, 5] = 0.16495; s6.data[10, 6] = -0.09334; s6.data[10, 7] = -0.28770; s6.data[10, 8] = -0.33885; s6.data[10, 9] = -0.25761; s6.data[10, 10] = -0.11968;

            // ma tran he so cho huong 6pi/8 rad
            matransothuc s7 = new matransothuc(11, 11);
            s7.data[0, 0] = -0.05581; s7.data[0, 1] = -0.18181; s7.data[0, 2] = -0.31657; s7.data[0, 3] = -0.40384; s7.data[0, 4] = -0.39445; s7.data[0, 5] = -0.27731; s7.data[0, 6] = -0.09092; s7.data[0, 7] = 0.09523; s7.data[0, 8] = 0.21790; s7.data[0, 9] = 0.25073; s7.data[0, 10] = 0.20961;
            s7.data[1, 0] = -0.18181; s7.data[1, 1] = -0.33699; s7.data[1, 2] = -0.45761; s7.data[1, 3] = -0.47579; s7.data[1, 4] = -0.35607; s7.data[1, 5] = -0.12428; s7.data[1, 6] = 0.13856; s7.data[1, 7] = 0.33749; s7.data[1, 8] = 0.41339; s7.data[1, 9] = 0.36788; s7.data[1, 10] = 0.25073;
            s7.data[2, 0] = -0.31657; s7.data[2, 1] = -0.45761; s7.data[2, 2] = -0.50648; s7.data[2, 3] = -0.40348; s7.data[2, 4] = -0.14990; s7.data[2, 5] = 0.17791; s7.data[2, 6] = 0.46130; s7.data[2, 7] = 0.60147; s7.data[2, 8] = 0.56978; s7.data[2, 9] = 0.41339; s7.data[2, 10] = 0.21790;
            s7.data[3, 0] = -0.40384; s7.data[3, 1] = -0.47579; s7.data[3, 2] = -0.40348; s7.data[3, 3] = -0.15957; s7.data[3, 4] = 0.20160; s7.data[3, 5] = 0.55643; s7.data[3, 6] = 0.77231; s7.data[3, 7] = 0.77880; s7.data[3, 8] = 0.60147; s7.data[3, 9] = 0.33749; s7.data[3, 10] = 0.09523;
            s7.data[4, 0] = -0.39445; s7.data[4, 1] = -0.35607; s7.data[4, 2] = -0.14990; s7.data[4, 3] = 0.20160; s7.data[4, 4] = 0.59232; s7.data[4, 5] = 0.87514; s7.data[4, 6] = 0.93941; s7.data[4, 7] = 0.77231; s7.data[4, 8] = 0.46130; s7.data[4, 9] = 0.13856; s7.data[4, 10] = -0.09092;
            s7.data[5, 0] = -0.27731; s7.data[5, 1] = -0.12428; s7.data[5, 2] = 0.17791; s7.data[5, 3] = 0.55643; s7.data[5, 4] = 0.87514; s7.data[5, 5] = 1.00000; s7.data[5, 6] = 0.87514; s7.data[5, 7] = 0.55643; s7.data[5, 8] = 0.17791; s7.data[5, 9] = -0.12428; s7.data[5, 10] = -0.27731;
            s7.data[6, 0] = -0.09092; s7.data[6, 1] = 0.13856; s7.data[6, 2] = 0.46130; s7.data[6, 3] = 0.77231; s7.data[6, 4] = 0.93941; s7.data[6, 5] = 0.87514; s7.data[6, 6] = 0.59232; s7.data[6, 7] = 0.20160; s7.data[6, 8] = -0.14990; s7.data[6, 9] = -0.35607; s7.data[6, 10] = -0.39445;
            s7.data[7, 0] = 0.09523; s7.data[7, 1] = 0.33749; s7.data[7, 2] = 0.60147; s7.data[7, 3] = 0.77880; s7.data[7, 4] = 0.77231; s7.data[7, 5] = 0.55643; s7.data[7, 6] = 0.20160; s7.data[7, 7] = -0.15957; s7.data[7, 8] = -0.40348; s7.data[7, 9] = -0.47579; s7.data[7, 10] = -0.40384;
            s7.data[8, 0] = 0.21790; s7.data[8, 1] = 0.41339; s7.data[8, 2] = 0.56978; s7.data[8, 3] = 0.60147; s7.data[8, 4] = 0.46130; s7.data[8, 5] = 0.17791; s7.data[8, 6] = -0.14990; s7.data[8, 7] = -0.40348; s7.data[8, 8] = -0.50648; s7.data[8, 9] = -0.45761; s7.data[8, 10] = -0.31657;
            s7.data[9, 0] = 0.25073; s7.data[9, 1] = 0.36788; s7.data[9, 2] = 0.41339; s7.data[9, 3] = 0.33749; s7.data[9, 4] = 0.13856; s7.data[9, 5] = -0.12428; s7.data[9, 6] = -0.35607; s7.data[9, 7] = -0.47579; s7.data[9, 8] = -0.45761; s7.data[9, 9] = -0.33699; s7.data[9, 10] = -0.18181;
            s7.data[10, 0] = 0.20961; s7.data[10, 1] = 0.25073; s7.data[10, 2] = 0.21790; s7.data[10, 3] = 0.09523; s7.data[10, 4] = -0.09092; s7.data[10, 5] = -0.27731; s7.data[10, 6] = -0.39445; s7.data[10, 7] = 0.40384; s7.data[10, 8] = -0.31657; s7.data[10, 9] = -0.18181; s7.data[10, 10] = -0.05581;

            // ma tran he so cho huong 7pi/8 rad
            matransothuc s8 = new matransothuc(11, 11);
            s8.data[0, 0] = -0.11968; s8.data[0, 1] = -0.20828; s8.data[0, 2] = -0.30619; s8.data[0, 3] = -0.39229; s8.data[0, 4] = -0.44375; s8.data[0, 5] = -0.44480; s8.data[0, 6] = -0.39369; s8.data[0, 7] = -0.30375; s8.data[0, 8] = -0.19807; s8.data[0, 9] = -0.10083; s8.data[0, 10] = -0.02705;
            s8.data[1, 0] = -0.25761; s8.data[1, 1] = -0.36417; s8.data[1, 2] = -0.45562; s8.data[1, 3] = -0.50485; s8.data[1, 4] = -0.49199; s8.data[1, 5] = -0.41395; s8.data[1, 6] = -0.28735; s8.data[1, 7] = -0.14291; s8.data[1, 8] = -0.01365; s8.data[1, 9] = 0.07691; s8.data[1, 10] = 0.012105;
            s8.data[2, 0] = -0.33885; s8.data[2, 1] = -0.41455; s8.data[2, 2] = -0.44348; s8.data[2, 3] = -0.40397; s8.data[2, 4] = -0.29238; s8.data[2, 5] = -0.12821; s8.data[2, 6] = 0.05100; s8.data[2, 7] = 0.20335; s8.data[2, 8] = 0.29814; s8.data[2, 9] = 0.32558; s8.data[2, 10] = 0.29655;
            s8.data[3, 0] = -0.28770; s8.data[3, 1] = -0.28067; s8.data[3, 2] = -0.20418; s8.data[3, 3] = -0.05531; s8.data[3, 4] = 0.14418; s8.data[3, 5] = 0.35162; s8.data[3, 6] = 0.51782; s8.data[3, 7] = 0.60553; s8.data[3, 8] = 0.60280; s8.data[3, 9] = 0.52468; s8.data[3, 10] = 0.40369;
            s8.data[4, 0] = -0.09334; s8.data[4, 1] = 0.01676; s8.data[4, 2] = 0.19441; s8.data[4, 3] = 0.41712; s8.data[4, 4] = 0.64024; s8.data[4, 5] = 0.81047; s8.data[4, 6] = 0.88562; s8.data[4, 7] = 0.85111; s8.data[4, 8] = 0.72437; s8.data[4, 9] = 0.54565; s8.data[4, 10] = 0.36071;
            s8.data[5, 0] = 0.16495; s8.data[5, 1] = 0.34697; s8.data[5, 2] = 0.56682; s8.data[5, 3] = 0.78241; s8.data[5, 4] = 0.94135; s8.data[5, 5] = 1.00000; s8.data[5, 6] = 0.94135; s8.data[5, 7] = 0.78241; s8.data[5, 8] = 0.56682; s8.data[5, 9] = 0.34697; s8.data[5, 10] = 0.16495;
            s8.data[6, 0] = 0.36071; s8.data[6, 1] = 0.54565; s8.data[6, 2] = 0.72437; s8.data[6, 3] = 0.85111; s8.data[6, 4] = 0.88562; s8.data[6, 5] = 0.81047; s8.data[6, 6] = 0.64024; s8.data[6, 7] = 0.41712; s8.data[6, 8] = 0.19441; s8.data[6, 9] = 0.01676; s8.data[6, 10] = -0.09334;
            s8.data[7, 0] = 0.40369; s8.data[7, 1] = 0.52468; s8.data[7, 2] = 0.60280; s8.data[7, 3] = 0.60553; s8.data[7, 4] = 0.51782; s8.data[7, 5] = 0.35162; s8.data[7, 6] = 0.14418; s8.data[7, 7] = -0.05531; s8.data[7, 8] = -0.20418; s8.data[7, 9] = -0.28067; s8.data[7, 10] = -0.28770;
            s8.data[8, 0] = 0.29655; s8.data[8, 1] = 0.32558; s8.data[8, 2] = 0.29814; s8.data[8, 3] = 0.20335; s8.data[8, 4] = 0.05100; s8.data[8, 5] = -0.12821; s8.data[8, 6] = -0.29238; s8.data[8, 7] = -0.40397; s8.data[8, 8] = -0.44348; s8.data[8, 9] = -0.41455; s8.data[8, 10] = -0.33885;
            s8.data[9, 0] = 0.12105; s8.data[9, 1] = 0.07691; s8.data[9, 2] = -0.01365; s8.data[9, 3] = -0.14291; s8.data[9, 4] = -0.28735; s8.data[9, 5] = -0.41395; s8.data[9, 6] = -0.49199; s8.data[9, 7] = -0.50485; s8.data[9, 8] = -0.45562; s8.data[9, 9] = -0.36417; s8.data[9, 10] = -0.25761;
            s8.data[10, 0] = -0.02705; s8.data[10, 1] = -0.10038; s8.data[10, 2] = -0.19807; s8.data[10, 3] = -0.30375; s8.data[10, 4] = -0.39369; s8.data[10, 5] = -0.44480; s8.data[10, 6] = -0.44375; s8.data[10, 7] = -0.39229; s8.data[10, 8] = -0.30619; s8.data[10, 9] = -0.20828; s8.data[10, 10] = -0.11968;

            matrannguyen gb = new matrannguyen(sohang, socot);
            matrannguyen g = new matrannguyen(sohang, socot);
            matrannguyen g1 = phanvung();
            g = mthuongmn(16);
            for (int i = 0; i < sohang; ++i)

                for (int j = 0; j < socot; ++j)
                {
                    if (g1.data[i, j] != 255)
                    {
                        int t;
                        t = huongmt(i, j);
                        if (g.data[i, j] == 0) gb.data[i, j] = (int)nhanchap1(i, j, s1);
                        if (g.data[i, j] == 1) gb.data[i, j] = (int)nhanchap1(i, j, s2);
                        if (g.data[i, j] == 2) gb.data[i, j] = (int)nhanchap1(i, j, s3);
                        if (g.data[i, j] == 3) gb.data[i, j] = (int)nhanchap1(i, j, s4);
                        if (g.data[i, j] == 4) gb.data[i, j] = (int)nhanchap1(i, j, s5);
                        if (g.data[i, j] == 5) gb.data[i, j] = (int)nhanchap1(i, j, s6);
                        if (g.data[i, j] == 6) gb.data[i, j] = (int)nhanchap1(i, j, s7);
                        if (g.data[i, j] == 7) gb.data[i, j] = (int)nhanchap1(i, j, s8);

                        gb.data[i, j] = (int)gb.data[i, j] / 20;
                        if (gb.data[i, j] < 0) gb.data[i, j] = 0;
                        if (gb.data[i, j] > 255) gb.data[i, j] = 255;
                    }
                    else gb.data[i, j] = 255;
                }
            return gb;
        }
        public matrannguyen loctrungbinh()
        {
            matransothuc matna = new matransothuc(3, 3);
            int i, j;
            for (i = 0; i < 3; ++i)
                for (j = 0; j < 3; ++j) matna.data[i, j] = 1;
            matna.data[1, 1] = 0;
            matrannguyen ketqua = this.nhanchap(matna);
            ketqua.chia(8);
            return ketqua;
        }
        public void chia(double t)
        {
            if (t == 0) return;
            int i, j;
            for (i = 0; i < sohang; i++)
                for (j = 0; j < socot; j++)
                {
                    data[i, j] = (int)(data[i, j] / t);

                }
        }
        public matrannguyen loctrungvi(int n)
        {
            matrannguyen ketqua = new matrannguyen(sohang, socot);
            ketqua.data = this.data;
            int i, j, k, l, g, h, tg;
            int[] list;
            for (i = 0; i < sohang - 1; ++i)
                for (j = 0; j < socot - 1; ++j)
                {
                    list = new int[n * n];
                    for (k = 0; k < n; ++k)
                        for (l = 0; l < n; ++l)
                        {
                            if ((i + k - 1 >= 0) && (j + l - 1 >= 0) && (i + k - 1 < sohang) && (j + l - 1 < socot))
                                list[k * n + l] = this.data[i + k - 1, j + l - 1];
                            //else list[k * n + l] = 0;
                        }
                    for (g = 0; g < n * n - 1; g++)
                        for (h = g + 1; h <= n * n - 1; ++h)
                        {
                            if (list[g] > list[h]) { tg = list[g]; list[g] = list[h]; list[h] = tg; }
                        }
                    if (Math.Abs(list[n * n / 2] - this.data[i, j]) > 50)
                        ketqua.data[i, j] = list[n * n / 2];
                    else ketqua.data[i, j] = this.data[i, j];
                }
            return ketqua;
        }
    }
    public class matransothuc : matran
    {
        public double[,] data;
        public matransothuc()
        {
            sohang = socot = -1;
        }
        public matransothuc(int sh, int sc)
        {
            socot = sc;
            sohang = sh;
            data = new double[sh, sc];
        }
    }
    public class matrannhiphan : matran
    {
        public bool[,] data;
        public matrannhiphan()
        {
            sohang = socot = 0;
            Bitmap bmp = new Bitmap(30, 30);
        }
        public matrannhiphan(int sh, int sc)
        {
            sohang = sh;
            socot = sc;
            data = new bool[sh, sc];
        }
        public matrannhiphan(int sh, int sc, bool giatri)
        {
            sohang = sh;
            socot = sc;
            int i, j;
            data = new bool[sh, sc];
            for (i = 0; i < this.sohang; ++i)
                for (j = 0; j < this.socot; ++j) data[i, j] = giatri;
        }
        public matrannhiphan(matrannguyen anhxam)
        {
            matrannguyen anh = anhxam.nhiphan();
            int i, j;
            sohang = anhxam.Sohang;
            socot = anhxam.Socot;
            data = new bool[sohang, socot];
            for (i = 0; i < sohang; ++i)
                for (j = 0; j < socot; ++j)
                {
                    data[i, j] = (anh.data[i, j] < 100);
                }

        }
        public matrannhiphan(matrannguyen anhxam, int nguong)
        {
            int i, j;
            this.sohang = anhxam.Sohang;
            this.socot = anhxam.Socot;
            data = new bool[sohang, socot];
            for (i = 0; i < this.sohang; ++i)
                for (j = 0; j < this.socot; ++j)
                    this.data[i, j] = (anhxam.data[i, j] < nguong);
        }
        public Bitmap ToBitmap()
        {
            Bitmap image = new Bitmap(this.sohang, this.socot);
            BitmapData bmpData = image.LockBits(new Rectangle(0, 0, sohang, socot), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            int remain = bmpData.Stride - bmpData.Width * 3;
            unsafe
            {
                byte* ptr = (byte*)bmpData.Scan0;

                for (int i = 0; i < bmpData.Height; i++)
                {
                    for (int j = 0; j < bmpData.Width; j++)
                    {

                        if (data[i, j]) ptr[0] = ptr[1] = ptr[2] = 0;
                        else ptr[0] = ptr[1] = ptr[2] = 255;
                        ptr += 3;
                    }
                    ptr += remain;
                }
            }
            image.UnlockBits(bmpData);
            return image;
        }
        public bool diembien(int i, int j)
        {
            int k, l; int dem = 0;
            if (!data[i, j]) return false;
            for (k = 0; k < 3; ++k)
            {
                for (l = 0; l < 3; ++l)
                {
                    if ((laygiatri(i + k - 1, j + l - 1) == 0)) dem++;
                }
            }
            if ((dem > 2) && (dem < 6)) return true;
            return false;
        }
        public bool diemxuong(int x, int y)
        {
            if (!data[x, y]) return false;
            int dem = 0;
            bool[] a = new bool[10]; int i, kq = 0;
            for (i = 0; i < 8; ++i) a[i] = lay(x, y, i);
            bool BGColor = false;
            if ((a[1] != BGColor) && (a[0] == BGColor) && (a[2] == BGColor))
                return true;
            if ((a[3] != BGColor) && (a[2] == BGColor) && (a[4] == BGColor))
                return true;
            if ((a[5] != BGColor) && (a[4] == BGColor) && (a[6] == BGColor))
                return true;
            if ((a[7] != BGColor) && (a[6] == BGColor) && (a[0] == BGColor))
                return true;
            for (i = 0; i < 8; i++)
                if (a[i] != BGColor) kq++;
            if (kq == 0 || kq == 1) return true;
            if (((a[0] == BGColor) && (a[4] == BGColor) &&
                (a[2] != BGColor) && (a[6] != BGColor)) ||
                ((a[2] == BGColor) && (a[6] == BGColor) &&
                (a[0] != BGColor) && (a[4] != BGColor)))
                return true;
            if (!a[0]) dem++;
            for (i = 1; i < 7; ++i)
                if ((!a[i]) && a[i - 1])
                    dem++;
            if ((!a[7]) && a[6] && a[0]) dem++;
            if (dem >= 2) return true;

            return false;
        }
        public matrannhiphan xoa()
        {
            int i, j;
            matrannguyen tg = this.trichdactrung();


            matrannhiphan ketqua = new matrannhiphan(sohang, socot);
            for (i = 0; i < sohang; ++i)
                for (j = 0; j < socot; ++j) ketqua.data[i, j] = this.data[i, j];
            for (i = 0; i < sohang; i++)
                for (j = 0; j < socot; ++j)
                    if (tg.data[i, j] == 1) if (this.chieudainhanh(i, j) < 3) ketqua.xoa_nhanh(i, j);
            return ketqua;
        }
        public int next(int huong)
        {
            if (huong == 7) return 0;
            return huong + 1;
        }
        public int prev(int huong)
        {
            if (huong == 0) return 7;
            return huong - 1;
        }
        public bool diemnoi(int x, int y)
        {
            if (data[x, y]) return false;
            bool[] danhdau = new bool[10];
            int i;
            int dem = demdiemden(x, y);
            if (dem < 2) return false;
            if (dem == 2)
            {
                if ((laygt(x, y, 0) && laygt(x, y, 6)) || (laygt(x, y, 0) && laygt(x, y, 2)) || (laygt(x, y, 2) && laygt(x, y, 4)) || (laygt(x, y, 4) && laygt(x, y, 6))) return false;
            }
            for (i = 0; i < 8; ++i) danhdau[i] = false;
            for (i = 0; i < 8; ++i)
                if (laygt(x, y, i))
                {
                    danhdau[next(i)] = danhdau[prev(i)] = true;
                    if (i % 2 == 1) danhdau[next(next(i))] = danhdau[prev(prev(i))] = true;

                }
            for (i = 0; i < 8; i++)
                if (laygt(x, y, i) && (!danhdau[i])) return true;
            return false;
        }
        public matrannhiphan noi()
        {
            matrannhiphan ketqua = new matrannhiphan(sohang, socot);
            int i, j;
            for (i = 0; i < sohang; ++i)
                for (j = 0; j < socot; ++j)
                {
                    ketqua.data[i, j] = this.data[i, j];
                }
            for (i = 0; i < sohang; ++i)
                for (j = 0; j < socot; ++j)
                    if (ketqua.diemnoi(i, j))
                        ketqua.data[i, j] = true;
            return ketqua;
        }
        public int laygiatri(int x, int y)
        {
            if (!hople(x, y)) return -1;
            if (data[x, y]) return 1;
            return 0;
        }
        public bool diembiendoi(int x, int y)
        {
            if (!data[x, y]) return false;
            if (laygiatri(x, y - 1) == 1 && laygiatri(x, y - 2) == 0 && laygiatri(x, y + 1) == 0) return true;
            if (laygiatri(x, y + 1) == 1 && laygiatri(x, y + 2) == 0 && laygiatri(x, y - 1) == 0) return true;
            if (laygiatri(x - 1, y) == 1 && laygiatri(x - 2, y) == 0 && laygiatri(x + 1, y) == 0) return true;
            if (laygiatri(x + 1, y) == 1 && laygiatri(x + 2, y) == 0 && laygiatri(x - 1, y) == 0) return true;
            if (laygiatri(x + 1, y + 1) == 1 && laygiatri(x - 1, y - 1) == 0 && laygiatri(x + 2, y + 2) == 0) return true;
            if (laygiatri(x - 1, y - 1) == 1 && laygiatri(x + 1, y + 1) == 0 && laygiatri(x - 2, y - 2) == 0) return true;
            if (laygiatri(x - 1, y + 1) == 1 && laygiatri(x - 2, y + 2) == 0 && laygiatri(x + 1, y - 1) == 0) return true;
            if (laygiatri(x + 1, y - 1) == 1 && laygiatri(x + 2, y - 2) == 0 && laygiatri(x - 1, y + 1) == 0) return true;
            return false;
        }
        public matrannhiphan tachbien()
        {
            matrannhiphan ketqua = new matrannhiphan(sohang, socot, false);
            int i, j;
            for (i = 0; i < this.sohang; ++i)
                for (j = 0; j < this.socot; ++j)
                {
                    if (diembien(i, j)) ketqua.data[i, j] = true;
                }
            return ketqua;
        }
        public matrannhiphan(matrannhiphan m)
        {
            int i, j;
            sohang = m.sohang;
            socot = m.socot;
            data = new bool[sohang, socot];
            for (i = 0; i < this.sohang; ++i)
                for (j = 0; j < this.socot; ++j)
                    data[i, j] = m.data[i, j];
        }
        public matrannhiphan timxuong()
        {
            int sodiemxoa = 0;
            matrannhiphan ketqua = new matrannhiphan(sohang, socot, false);
            //matrannhiphan mt_bien;
            ketqua.xetca();
            int i, j;
            matrannhiphan tg = new matrannhiphan(sohang, socot);
            for (i = 0; i < this.sohang; ++i)
                for (j = 0; j < this.socot; ++j)
                    tg.data[i, j] = data[i, j];
            matrannhiphan tg1 = new matrannhiphan(sohang, socot);
            for (i = 0; i < this.sohang; ++i)
                for (j = 0; j < this.socot; ++j)
                    tg1.data[i, j] = tg.data[i, j];
            do
            {
                sodiemxoa = 0;
                //mt_bien = tg.tachbien();
                for (i = 0; i < this.sohang; ++i)
                    for (j = 0; j < this.socot; ++j)
                        if (ketqua.xet[i, j])
                        {
                            // if(mt_bien.data[i,j])
                            if (tg.diembien(i, j))
                            {
                                if (tg.diemxuong(i, j))
                                {
                                    ketqua.data[i, j] = true; ketqua.xet[i, j] = false;
                                    sodiemxoa++;
                                }
                                else if (tg.diembiendoi(i, j) && tg1.diembiendoi(i, j))
                                {

                                    ketqua.xet[i, j] = false;
                                    tg.data[i, j] = tg1.data[i, j] = false;
                                    sodiemxoa++;

                                }
                                else
                                    if (!tg.diemxuong(i, j))
                                    {
                                        tg1.data[i, j] = false; ketqua.xet[i, j] = false;
                                        sodiemxoa++;
                                    }
                            }

                        };
                tg = new matrannhiphan(sohang, socot);
                for (i = 0; i < this.sohang; ++i)
                    for (j = 0; j < this.socot; ++j)
                        tg.data[i, j] = tg1.data[i, j];
            } while (sodiemxoa > 0);
            return tg;
        }
        public matrannhiphan co()
        {
            matrannhiphan ketqua = new matrannhiphan(sohang, socot);
            int i, j, k, l;
            for (i = 0; i < sohang; ++i)
                for (j = 0; j < socot; ++j) ketqua.data[i, j] = data[i, j];
            for (i = 0; i < sohang; ++i)
                for (j = 0; j < socot; ++j)
                    if (!data[i, j])
                    {
                        for (k = 0; k < 3; ++k)
                            for (l = 0; l < 3; ++l)
                            {
                                if (hople(i + k - 1, j + l - 1)) ketqua.data[i + k - 1, j + l - 1] = false;
                            }
                    }
            return ketqua;
        }
        public matrannhiphan gian()
        {
            matrannhiphan ketqua = new matrannhiphan(sohang, socot);
            int i, j, k, l;
            for (i = 0; i < sohang; ++i)
                for (j = 0; j < socot; ++j) ketqua.data[i, j] = data[i, j];
            for (i = 0; i < sohang; ++i)
                for (j = 0; j < socot; ++j)
                    if (data[i, j])
                    {
                        for (k = 0; k < 3; ++k)
                            for (l = 0; l < 3; ++l)
                            {
                                if (hople(i + k - 1, j + l - 1)) ketqua.data[i + k - 1, j + l - 1] = true;
                            }
                    }
            return ketqua;
        }
        int diemdactrung(int i, int j)
        {
            int k;
            if (!data[i, j]) return 0;
            int dem = 0;
            for (k = 0; k < 8; ++k) if (laygt(i, j, k)) dem++;
            if (dem == 2) return 0;
            if (dem == 1) return 1;
            if (dem == 3) return 2;
            if (dem >= 4) return 3;
            return 3;
        }
        public int sosanh(matrannhiphan anh2)
        {
            int ketqua = 0;
            int i, j;
            for (i = 0; i < Sohang; ++i)
                for (j = 0; j < socot; ++j)
                {
                    if (data[i, j] != anh2.data[i, j]) ketqua++;
                }
            return ketqua;
        }
        public matrannguyen trichdactrung()
        {
            matrannguyen ketqua = new matrannguyen(sohang, socot);
            int i, j;
            for (i = 0; i < sohang; ++i)
                for (j = 0; j < socot; ++j)
                    ketqua.data[i, j] = diemdactrung(i, j);
            return ketqua;
        }
        public void chuanhoa(int x, int y)
        {
            bool[] tg = new bool[10];
            tg[0] = (laygiatri(x, y - 1) == 1);
            tg[1] = (laygiatri(x + 1, y) == 1);
            tg[2] = (laygiatri(x, y + 1) == 1);
            tg[3] = (laygiatri(x - 1, y) == 1);
            int i;
            for (i = 1; i < 4; ++i)
                if (tg[i] && tg[i - 1]) data[x, y] = false;
            if (tg[0] && tg[3]) data[x, y] = false;
        }
        bool lay(int x, int y, int huong)
        {
            if (huong == 7) if (hople(x - 1, y)) return data[x - 1, y];
            if (huong == 6) if (hople(x - 1, y - 1)) return data[x - 1, y - 1];
            if (huong == 5) if (hople(x, y - 1)) return data[x, y - 1];
            if (huong == 4) if (hople(x + 1, y - 1)) return data[x + 1, y - 1];
            if (huong == 3) if (hople(x + 1, y)) return data[x + 1, y];
            if (huong == 2) if (hople(x + 1, y + 1)) return data[x + 1, y + 1];
            if (huong == 1) if (hople(x, y + 1)) return data[x, y + 1];
            if (huong == 0) if (hople(x - 1, y + 1)) return data[x - 1, y + 1];

            return true;
        }
        bool laygt(int x, int y, int huong)
        {
            if (huong == 6) if (hople(x - 1, y - 1)) return data[x - 1, y - 1];
            if (huong == 5) if (hople(x, y - 1)) return data[x, y - 1];
            if (huong == 4) if (hople(x + 1, y - 1)) return data[x + 1, y - 1];
            if (huong == 3) if (hople(x + 1, y)) return data[x + 1, y];
            if (huong == 2) if (hople(x + 1, y + 1)) return data[x + 1, y + 1];
            if (huong == 1) if (hople(x, y + 1)) return data[x, y + 1];
            if (huong == 0) if (hople(x - 1, y + 1)) return data[x - 1, y + 1];
            if (huong == 7) if (hople(x - 1, y)) return data[x - 1, y];
            return false;
        }
        int nguoc(int huong)
        {
            if (huong == 6) return 2;
            if (huong == 2) return 6;
            if (huong == 5) return 1;
            if (huong == 1) return 5;
            if (huong == 4) return 0;
            if (huong == 0) return 4;
            if (huong == 7) return 3;
            if (huong == 3) return 7;
            return 7;
        }
        int getx(int x, int y, int huong)
        {
            if (huong == 6 || huong == 7 || huong == 0) return (x - 1);
            if (huong == 5 || huong == 1) return x;
            return (x + 1);
        }
        int gety(int x, int y, int huong)
        {
            if (huong == 6 || huong == 5 || huong == 4) return (y - 1);
            if (huong == 3 || huong == 7) return y;
            return (y + 1);
        }
        public matrannhiphan chuanhoa()
        {
            matrannhiphan ketqua = new matrannhiphan(sohang, socot);
            int i, j;
            for (i = 0; i < sohang; ++i)
                for (j = 0; j < socot; ++j)
                    ketqua.data[i, j] = this.data[i, j];
            for (i = 0; i < sohang; ++i)
                for (j = 0; j < socot; ++j)
                    ketqua.chuanhoa(i, j);
            return ketqua;
        }
        public int demdiemden(int x, int y)
        {
            int i, dem = 0;
            for (i = 0; i < 8; ++i)
                if (laygt(x, y, i)) dem++;
            return dem;
        }
        public int chieudainhanh(int x, int y)
        {
            int truoc = -1, i = x, j = y, k, dem = 1;
            bool ok = false;
            if (!data[x, y]) return 0;
            if (demdiemden(x, y) == 0) return 1;
            if (demdiemden(x, y) > 1) return 0;
            {
                if (data[i, j] == false) return dem;
                ok = false;
                for (k = 0; k < 8; ++k)
                {
                    if (laygt(i, j, k) && (k != truoc)) { ok = true; break; }
                }
                if (ok)
                {
                    dem++;
                    truoc = nguoc(k);
                    i = getx(i, j, k);
                    j = gety(i, j, k);
                }
                dem++;
                //MessageBox.Show(demdiemden(i, j).ToString() + " " + ok.ToString());
            }
            while ((ok) && (demdiemden(i, j) == 2) && dem < 4) ;
            return dem;
        }
        public bool xoa_nhanh(int x, int y)
        {
            int i = x, j = y, k;
            bool ok = false;
            if (!data[i, j]) return false;
            if (chieudainhanh(i, j) < 0) return false;
            if (demdiemden(x, y) > 1) return false;
            if (demdiemden(x, y) == 1) { data[x, y] = false; return true; }
            for (k = 0; k < 8; ++k)
                if (laygt(i, j, k)) { ok = true; break; }
            if (ok)
            {
                i = getx(i, j, k);
                j = gety(i, j, k);
                xoa_nhanh(i, j);
            }
            return true;
        }
        public bool[] t_vter(int i, int j)
        {
            bool[] kq = new bool[8];
            if (i - 1 >= 0 || j - 1 >= 0 || i - 1 > 512 || j - 1 > 512)
            {
                kq[7] = data[i - 1, j - 1];
                kq[0] = data[i - 1, j];
                kq[1] = data[i - 1, j + 1];
                kq[2] = data[i, j + 1];
                kq[3] = data[i + 1, j + 1];
                kq[4] = data[i + 1, j];
                kq[5] = data[i + 1, j - 1];
                kq[6] = data[i, j - 1];
            }
            return kq;
        }
        public matrannhiphan t_mtb()
        {
            matrannhiphan kq = new matrannhiphan(sohang, socot, false);
            for (int i = 0; i < kq.socot; i++)
                for (int j = 0; j < kq.socot; j++)
                {
                    bool tg = false;
                    tg = diembien(i, j);
                    if (tg == true)
                        kq.data[i, j] = true;
                    else
                        kq.data[i, j] = false;
                }
            return kq;
        }
        public matrannhiphan t_mtxuong()
        {
            matrannhiphan kq = new matrannhiphan(sohang, socot, false);
            matrannhiphan tg = new matrannhiphan(sohang, socot, false);
            bool xoa = false;
            do
            {
                int dem = 0;
                tg = t_mtb();
                for (int i = 1; i < kq.socot - 1; i++)
                    for (int j = 1; j < kq.socot - 1; j++)
                    {
                        if (tg.data[i, j] == true)
                        {
                            bool xet = false;
                            xet = t_dxuong(i, j);
                            if (xet == false)
                            {
                                data[i, j] = false;
                                dem++;
                            }
                        }

                    }
                if (dem == 0) xoa = true;
            }
            while (xoa == false);
            kq = t_conver();
            return kq;
        }
        public bool t_dxuong(int i, int j)
        {
            int kq = 0;
            bool[] a = new bool[8];
            a = t_vter(i, j);
            bool BGColor = false;
            if ((a[1] != BGColor) && (a[0] == BGColor) && (a[2] == BGColor))
                return true;
            if ((a[3] != BGColor) && (a[2] == BGColor) && (a[4] == BGColor))
                return true;
            if ((a[5] != BGColor) && (a[4] == BGColor) && (a[6] == BGColor))
                return true;
            if ((a[7] != BGColor) && (a[6] == BGColor) && (a[0] == BGColor))
                return true;
            for (int k = 0; k < 8; k++)
                if (a[k] != BGColor) kq++;
            if (kq == 0 || kq == 1) return true;
            if (((a[0] == BGColor) && (a[4] == BGColor) &&
                 (a[2] != BGColor) && (a[6] != BGColor)) ||
                 ((a[2] == BGColor) && (a[6] == BGColor) &&
                 (a[0] != BGColor) && (a[4] != BGColor)))
                return true;

            return false;
        }
        public bool t_xddoi(int i, int j)
        {
            bool[] vter = new bool[8];
            bool tg = false;
            vter = t_vter(i, j);
            if ((vter[0] == true) && (vter[2] == true)) tg = true;
            if ((vter[2] == true) && (vter[4] == true)) tg = true;
            if ((vter[4] == true) && (vter[6] == true)) tg = true;
            if ((vter[6] == true) && (vter[0] == true)) tg = true;
            return tg;
        }
        public matrannhiphan t_xdoi()
        {
            matrannhiphan kq = new matrannhiphan(sohang, socot, false);
            for (int i = 0; i < kq.sohang; i++)
                for (int j = 0; j < kq.socot; j++)
                {
                    if (this.data[i, j] == true)
                    {
                        bool xet = t_ddoi(i, j);
                        if (xet == true)
                        {
                            bool xet1 = t_xddoi(i, j);
                            if (xet1 == true)
                                this.data[i, j] = false;
                        }
                    }
                }
            kq = t_conver();
            kq = kq.t_xdoi();
            return kq;
        }
        public bool t_ddoi(int i, int j)
        {
            bool[] vter = new bool[8];
            vter = t_vter(i, j);
            int dem = 0;
            for (int k = 0; k < 8; k++)
            {
                if (data[i, j] == true) dem++;
            }
            if (dem == 2) return true;
            return false;
        }
        public matrannhiphan t_conver()
        {
            matrannhiphan kq = new matrannhiphan(socot, sohang, false);
            for (int i = 0; i < kq.socot; i++)
                for (int j = 0; j < kq.socot; j++)
                {
                    kq.data[i, j] = data[i, j];
                }
            return kq;
        }

    }
    public class vnImageProcess
    {
        public static Bitmap ConvertToGrayscale(Bitmap source)
        {

            Bitmap bm = new Bitmap(source.Width, source.Height);

            for (int y = 0; y < bm.Height; y++)
            {

                for (int x = 0; x < bm.Width; x++)
                {

                    Color c = source.GetPixel(x, y);

                    int luma = (int)(c.R * 0.3 + c.G * 0.59 + c.B * 0.11);

                    bm.SetPixel(x, y, Color.FromArgb(luma, luma, luma));

                }

            }

            return bm;

        }

        public static bool EdgeDetectDifference(Bitmap b, byte nThreshold)
        {
            // This one works by working out the greatest difference between a 
            // pixel and it's eight neighbours. The threshold allows softer edges 
            // to be forced down to black, use 0 to negate it's effect.
            Bitmap b2 = (Bitmap)b.Clone();

            // GDI+ still lies to us - the return format is BGR, NOT RGB.
            BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
                ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            BitmapData bmData2 = b2.LockBits(new Rectangle(0, 0, b.Width, b.Height),
                ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            int stride = bmData.Stride;
            System.IntPtr Scan0 = bmData.Scan0;
            System.IntPtr Scan02 = bmData2.Scan0;

            unsafe
            {
                byte* p = (byte*)(void*)Scan0;
                byte* p2 = (byte*)(void*)Scan02;

                int nOffset = stride - b.Width * 3;
                int nWidth = b.Width * 3;

                int nPixel = 0, nPixelMax = 0;

                p += stride;
                p2 += stride;

                for (int y = 1; y < b.Height - 1; ++y)
                {
                    p += 3;
                    p2 += 3;

                    for (int x = 3; x < nWidth - 3; ++x)
                    {
                        nPixelMax = Math.Abs((p2 - stride + 3)[0] - (p2 + stride - 3)[0]);
                        nPixel = Math.Abs((p2 + stride + 3)[0] - (p2 - stride - 3)[0]);
                        if (nPixel > nPixelMax) nPixelMax = nPixel;

                        nPixel = Math.Abs((p2 - stride)[0] - (p2 + stride)[0]);
                        if (nPixel > nPixelMax) nPixelMax = nPixel;

                        nPixel = Math.Abs((p2 + 3)[0] - (p2 - 3)[0]);
                        if (nPixel > nPixelMax) nPixelMax = nPixel;

                        if (nPixelMax < nThreshold) nPixelMax = 0;

                        p[0] = (byte)nPixelMax;

                        ++p;
                        ++p2;
                    }

                    p += 3 + nOffset;
                    p2 += 3 + nOffset;
                }
            }

            b.UnlockBits(bmData);
            b2.UnlockBits(bmData2);

            return true;

        }

        public static bool Brighten(Bitmap b, int nBrightness)
        {
            // GDI+ return format is BGR, NOT RGB.
            BitmapData bmData
                = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
                ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            int stride = bmData.Stride;
            System.IntPtr Scan0 = bmData.Scan0;

            unsafe
            {
                int nVal;
                byte* p = (byte*)(void*)Scan0;
                int nOffset = stride - b.Width * 3;
                int nWidth = b.Width * 3;
                for (int y = 0; y < b.Height; ++y)
                {
                    for (int x = 0; x < nWidth; ++x)
                    {
                        nVal = (int)(p[0] + nBrightness);
                        if (nVal < 0) nVal = 0;
                        if (nVal > 255) nVal = 255;
                        p[0] = (byte)nVal;
                        ++p;
                    }
                    p += nOffset;
                }
            }

            b.UnlockBits(bmData);
            return true;
        }//Brighten

        /// <summary>
        /// It is the Wiener Filter Function
        /// </summary>
        /// <param name="use">It is of Type Bitmap </param>
        /// <returns>Return Bitmap after Applying Wiener Filter to it.</returns>
        public static Bitmap Wiener(Bitmap use)
        {
            Bitmap wien = new Bitmap(use.Height, use.Width);

            //Variable's used for Calculations
            int i, j, N;
            int tmp = 0;
            int mM, M1, mVAR;


            // Calculating the Total Mean of the image
            for (i = 0; i < use.Height; i++)
            {
                for (j = 0; j < use.Width - 1; j++)
                {
                    Color clr = use.GetPixel(i, j);
                    tmp = tmp + Convert.ToInt32(clr.R);
                }
            }
            N = use.Height * use.Width;
            mM = Convert.ToInt32(Math.Abs(tmp / N));

            // Calculating the Total Variance of the image
            tmp = 0;
            for (i = 0; i < use.Height; i++)
            {
                for (j = 0; j < use.Width; j++)
                {
                    Color clr = use.GetPixel(i, j);
                    M1 = ((Convert.ToInt32(clr.R) - mM) * (Convert.ToInt32(clr.R) - mM));
                    tmp = tmp + M1;
                }
            }
            mVAR = Convert.ToInt32(Math.Abs(tmp / N));

            //Convert the image to integer array
            int[,] image = new int[512, 512];
            for (i = 0; i < use.Height; i++)
            {
                for (j = 0; j < use.Width; j++)
                {
                    image[i, j] = Convert.ToInt32(use.GetPixel(i, j).R);
                }
            }

            int Block = 5;
            int BlockSqr = 25;

            // Internal Block Processing
            for (i = Block; i < use.Height - Block; i = i + 1)
                for (j = Block; j < use.Width - Block; j = j + 1)
                {
                    int lM, lVAR;

                    // Calculating the Mean of the Block
                    tmp = 0;
                    for (int k = i - Block; k < i + Block; k = k + 1)
                    {
                        for (int l = j - Block; l < j + Block; l = l + 1)
                        {
                            tmp = tmp + image[k, l];
                        }
                    }
                    lM = Convert.ToInt32(Math.Abs(tmp / BlockSqr));

                    // Calculating the Variance of the Block
                    tmp = 0;
                    M1 = 0;
                    for (int k = i - Block; k < Block + i; k = k + 1)
                    {
                        for (int l = j - Block; l < Block + j; l = l + 1)
                        {
                            M1 = ((image[k, l] - Convert.ToInt32(lM)) * (image[k, l] - Convert.ToInt32(lM)));
                            tmp = tmp + M1;
                        }
                    }
                    lVAR = Convert.ToInt32(Math.Abs(tmp / BlockSqr));

                    //Putting the filtered value

                    double tm = (lVAR - mVAR);
                    double tm1;
                    try
                    {
                        tm1 = tm / lVAR;
                    }
                    catch
                    {
                        tm1 = 0;
                    }
                    finally
                    {
                        tm1 = 0;
                    }
                    int mm = Convert.ToInt32(image[i, j] - lM);
                    double tm2 = tm1 * (image[i, j] - lM);
                    int A = lM + Convert.ToInt32(tm2);

                    if (A < 255)
                        wien.SetPixel(i, j, Color.FromArgb(255, A, A, A));

                }
            return (wien);
        }


        /// <summary>
        /// Applying LowPass Filter To the Bitmap
        /// </summary>
        /// <param name="use">Takes Bitmap as the input</param>
        /// <returns>Returns Bitmap as the output after Performing Lowpass filtering</returns>
        public static Bitmap LowPass(Bitmap use)
        {
            int Rows = use.Height;
            int Cols = use.Width;
            int pixel = 0;
            Bitmap LowFilter = new Bitmap(use.Height, use.Width);


            for (int r = 1; r < Rows - 1; r++)
                for (int c = 1; c < Cols - 1; c++)
                {
                    Color z1 = use.GetPixel(r - 1, c - 1);
                    Color z2 = use.GetPixel(r - 1, c);
                    Color z3 = use.GetPixel(r - 1, c + 1);
                    Color z4 = use.GetPixel(r, c - 1);
                    Color z5 = use.GetPixel(r, c);
                    Color z6 = use.GetPixel(r, c + 1);
                    Color z7 = use.GetPixel(r + 1, c - 1);
                    Color z8 = use.GetPixel(r + 1, c);
                    Color z9 = use.GetPixel(r + 1, c + 1);
                    /* Apply Lowpass operator. */
                    pixel = Convert.ToInt32(z3.R) + Convert.ToInt32(z1.R) + Convert.ToInt32(z6.R) + Convert.ToInt32(z4.R) + Convert.ToInt32(z9.R) + Convert.ToInt32(z7.R) + Convert.ToInt32(z2.R) + Convert.ToInt32(z5.R) + Convert.ToInt32(z8.R);
                    pixel = pixel / 9;
                    /* Check magnitude */
                    //if (pixel <255) 
                    LowFilter.SetPixel(r, c, Color.FromArgb(255, pixel, pixel, pixel));
                }
            return (LowFilter);
        }

        /// <summary>
        /// Convert Bitmap from Grey to Binary Using Threshold Method using Mean
        /// </summary>
        /// <param name="use">Takes Bitmap as Input</param>
        /// <returns>Return Binary Image </returns>
        public static Bitmap ThreshMean(Bitmap use)
        {
            Bitmap ThreshHold = new Bitmap(use.Height, use.Width);

            int Rows = 15;
            int Cols = 15;

            for (int i = 0; i < use.Height; i = i + 15)
                for (int j = 0; j < use.Width; j = j + 15)
                {

                    int r, c;
                    int pixel = 0;
                    int[] arr = new int[255];
                    int cnt = 0;

                    for (r = i; r < Rows + i; r++)
                        for (c = j; c < Cols + j; c++)
                        {
                            Color z1 = use.GetPixel(r, c);
                            arr[cnt] = Convert.ToInt32(z1.R);
                            cnt++;
                        }
                    for (int k = 0; k < 255; k++)
                        pixel = pixel + arr[k];

                    pixel = pixel / 255;

                    for (r = i; r < Rows + i; r++)
                        for (c = j; c < Cols + j; c++)
                        {
                            //Color z1 = hist.GetPixel(r,c);
                            Color z1 = use.GetPixel(r, c);
                            if (pixel < Convert.ToInt32(z1.R))
                                ThreshHold.SetPixel(r, c, Color.FromArgb(255, 0, 0, 0));
                            else
                                ThreshHold.SetPixel(r, c, Color.FromArgb(255, 255, 255, 255));
                        }

                }
            return (ThreshHold);
        }
        /// <summary>
        /// Does Histogram Processing on the Grey Scale Image
        /// </summary>
        /// <param name="use">Takes Bitmap as Input</param>
        /// <returns>Return Bitmap which is Histogram Processed</returns>
        public static Bitmap Histogram(Bitmap use)
        {
            int r, c, tmp = 0;
            double[] Pixel = new double[256];
            double[] Prob = new double[256];


            //Calculating the number of pixel of same type

            for (r = 0; r < use.Height; r++)
            {
                for (c = 0; c < use.Width; c++)
                {
                    Color cr = use.GetPixel(r, c);
                    tmp = Convert.ToInt32(cr.R);
                    Pixel[tmp] = Pixel[tmp] + 1;
                }
            }
            //Total Number of Pixels
            int tot = use.Height * use.Width;

            //Calculating the probability
            for (r = 0; r < 256; r++)
            {
                if (Pixel[r] != 0)
                {
                    Pixel[r] = Pixel[r] / tot;
                }
            }

            //Calculating the cumulative probability
            Prob[0] = Pixel[0];
            for (r = 1; r < 256; r++)
            {
                Prob[r] = Prob[r - 1] + Pixel[r];
            }

            // Generating New Graylevel Values
            for (r = 0; r < 256; r++)
            {
                Prob[r] = Prob[r] * 255;
            }
            Bitmap hist = new Bitmap(use.Height, use.Width);
            for (r = 0; r < use.Height; r++)
            {
                for (c = 0; c < use.Width; c++)
                {
                    Color cr = use.GetPixel(r, c);
                    tmp = Convert.ToInt32(cr.R);
                    hist.SetPixel(r, c, Color.FromArgb(255, Convert.ToInt32(Prob[tmp]), Convert.ToInt32(Prob[tmp]), Convert.ToInt32(Prob[tmp])));
                }
            }
            //End of Histogram
            return (hist);
        }

        /// <summary>
        /// Does the Normalization of the Grey Scale Image
        /// </summary>
        /// <param name="use">Takes Bitmap as Input</param>
        /// <returns>Returns Normalized Bitmap</returns>
        public static Bitmap Normalize(Bitmap use)
        {
            Bitmap normalized = new Bitmap(use.Height, use.Width);

            //Variable's used for Calculations
            int i, j, N;
            int tmp = 0;
            int M, M1, VAR;

            // Calculating the Mean of the image
            for (i = 0; i < use.Height - 1; i++)
            {
                for (j = 0; j < use.Width - 1; j++)
                {
                    Color clr = use.GetPixel(i, j);
                    tmp = tmp + Convert.ToInt32(clr.R);
                }
            }
            N = use.Height * use.Width;
            M = Convert.ToInt32(Math.Abs(tmp / N));

            // Calculating the Variance of the image
            tmp = 0;
            for (i = 0; i < use.Height - 1; i++)
            {
                for (j = 0; j < use.Width - 1; j++)
                {
                    Color clr = use.GetPixel(i, j);
                    M1 = ((Convert.ToInt32(clr.R) - M) * (Convert.ToInt32(clr.R) - M));
                    tmp = tmp + M1;
                }
            }
            VAR = Convert.ToInt32(Math.Abs(tmp / N));

            int MO = 100, VARO = 100, newInten;
            Color Inten;

            for (i = 0; i < use.Height - 1; i++)
            {
                for (j = 0; j < use.Width - 1; j++)
                {
                    Inten = use.GetPixel(i, j);
                    if (Convert.ToInt32(Inten.R) > M)
                    {
                        newInten = MO + Convert.ToInt32(Math.Sqrt((VARO * ((Convert.ToInt32(Inten.R) - M) * (Convert.ToInt32(Inten.R) - M))) / VAR));
                        normalized.SetPixel(i, j, Color.FromArgb(255, Convert.ToInt32(newInten), Convert.ToInt16(newInten), Convert.ToInt16(newInten)));
                    }
                    else
                    {
                        newInten = MO - Convert.ToInt32(Math.Sqrt((VARO * ((Convert.ToInt32(Inten.R) - M) * (Convert.ToInt32(Inten.R) - M))) / VAR));
                        normalized.SetPixel(i, j, Color.FromArgb(255, Convert.ToInt32(newInten), Convert.ToInt16(newInten), Convert.ToInt16(newInten)));
                    }
                }
            }
            return (normalized);
            //End of Normalization
        }





        /// <summary>
        /// This Function Does Sekelotonization to the Binary Image
        /// </summary>
        /// <param name="use">Takes Binary Image as Input</param>
        /// <returns>Return Thined Binar Image</returns>
        public static Bitmap ThinMean(Bitmap use)
        {

            bool success3 = true;
            while (success3)
            {
                bool success = false;
                bool success2 = false;
                int count;
                int count2;
                int num_transitions;
                int[,] picture = new int[300, 300];
                int[,] temp_array = new int[300, 300];
                int transitions;
                int[,] temp = new int[300, 300];

                for (int h = 0; h < 300; h++)
                    for (int w = 0; w < 300; w++)
                    {
                        picture[h, w] = Convert.ToInt32(use.GetPixel(h, w).R);
                    }

                for (int i = 1; i < 300 - 1; i++)
                {
                    for (int j = 1; j < 300 - 1; j++)
                    {
                        count = 0;
                        num_transitions = 0;

                        // check  for N(p)
                        if (picture[i, j] == 255)
                        {
                            if (picture[i - 1, j - 1] != 0)
                                count++;
                            if (picture[i, j - 1] != 0)
                                count++;
                            if (picture[i + 1, j - 1] != 0)
                                count++;
                            if (picture[i + 1, j] != 0)
                                count++;
                            if (picture[i - 1, j] != 0)
                                count++;
                            if (picture[i + 1, j + 1] != 0)
                                count++;
                            if (picture[i, j + 1] != 0)
                                count++;
                            if (picture[i - 1, j + 1] != 0)
                                count++;

                            if (count != 8)
                            {
                                // 2 <= N(p) <= 6
                                if (count >= 2 && count <= 6)
                                {
                                    if (picture[i - 1, j] == 0 && picture[i - 1, j + 1] == 255)
                                        num_transitions++;
                                    if (picture[i - 1, j + 1] == 0 && picture[i, j + 1] == 255)
                                        num_transitions++;
                                    if (picture[i, j + 1] == 0 && picture[i + 1, j + 1] == 255)
                                        num_transitions++;
                                    if (picture[i + 1, j + 1] == 0 && picture[i + 1, j] == 255)
                                        num_transitions++;
                                    if (picture[i + 1, j] == 0 && picture[i + 1, j - 1] == 255)
                                        num_transitions++;
                                    if (picture[i + 1, j - 1] == 0 && picture[i, j - 1] == 255)
                                        num_transitions++;
                                    if (picture[i, j - 1] == 0 && picture[i - 1, j - 1] == 255)
                                        num_transitions++;
                                    if (picture[i - 1, j - 1] == 0 && picture[i - 1, j] == 255)
                                        num_transitions++;

                                    //S(p) = 1
                                    if (num_transitions == 1)
                                    {
                                        // if p2 * p4 * p6 = 0
                                        if (picture[i - 1, j] == 0 || picture[i, j + 1] == 0 ||
                                            picture[i + 1, j] == 0)
                                        {
                                            // if p4 * p6 * p8 = 0 
                                            if (picture[i, j + 1] == 0 || picture[i + 1, j] == 0 || picture[i, j - 1] == 0)
                                            {
                                                temp_array[i, j] = 0;
                                                success = true;
                                            }
                                            else
                                                temp_array[i, j] = 255;
                                        }
                                        else
                                            temp_array[i, j] = 255;
                                    }
                                    else
                                        temp_array[i, j] = 255;
                                }
                                else
                                    temp_array[i, j] = 255;
                            }
                            else
                                temp_array[i, j] = 255;
                        }
                        else
                            temp_array[i, j] = 0;
                    }
                }
                //copy thinned image back to original
                for (int a = 0; a < 300; a++)
                {
                    for (int b = 0; b < 300; b++)
                        picture[a, b] = temp_array[a, b];
                }


                // step 2 of the thinning algorithm 
                for (int k = 0; k < 300; k++)
                {
                    for (int l = 0; l < 300; l++)
                    {
                        count2 = 0;
                        transitions = 0;
                        if (picture[k, l] == 255)
                        {
                            if (picture[k - 1, l - 1] != 0)
                                count2++;
                            if (picture[k, l - 1] != 0)
                                count2++;
                            if (picture[k + 1, l - 1] != 0)
                                count2++;
                            if (picture[k + 1, l] != 0)
                                count2++;
                            if (picture[k - 1, l] != 0)
                                count2++;
                            if (picture[k + 1, l + 1] != 0)
                                count2++;
                            if (picture[k, l + 1] != 0)
                                count2++;
                            if (picture[k - 1, l + 1] != 0)
                                count2++;

                            if (count2 != 8)
                            {
                                if (count2 >= 2 && count2 <= 6)
                                {
                                    if (picture[k - 1, l] == 0 && picture[k - 1, l + 1] == 255)
                                        transitions++;
                                    if (picture[k - 1, l + 1] == 0 && picture[k, l + 1] == 255)
                                        transitions++;
                                    if (picture[k, l + 1] == 0 && picture[k + 1, l + 1] == 255)
                                        transitions++;
                                    if (picture[k + 1, l + 1] == 0 && picture[k + 1, l] == 255)
                                        transitions++;
                                    if (picture[k + 1, l] == 0 && picture[k + 1, l - 1] == 255)
                                        transitions++;
                                    if (picture[k + 1, l - 1] == 0 && picture[k, l - 1] == 255)
                                        transitions++;
                                    if (picture[k, l - 1] == 0 && picture[k - 1, l - 1] == 255)
                                        transitions++;
                                    if (picture[k - 1, l - 1] == 0 && picture[k - 1, l] == 255)
                                        transitions++;

                                    if (transitions == 1)
                                    {
                                        // if p2 * p4 * p8 = 0
                                        if (picture[k - 1, l] == 0 || picture[k, l + 1] == 0 || picture[k, l - 1] == 0)
                                        {
                                            // if p2 * p6 * p8
                                            if (picture[k - 1, l] == 0 || picture[k + 1, l] == 0 || picture[k, l - 1] == 0)
                                            {
                                                temp[k, l] = 0;
                                                success2 = true;
                                            }
                                            else
                                                temp[k, l] = 255;
                                        }
                                        else
                                            temp[k, l] = 255;
                                    }
                                    else
                                        temp[k, l] = 255;
                                }
                                else
                                    temp[k, l] = 255;
                            }
                            else
                                temp[k, l] = 255;
                        }
                        else
                            temp[k, l] = 0;
                    }
                }

                for (int a = 0; a < 300; a++)
                    for (int b = 0; b < 300; b++)
                    {
                        int tmp = temp[a, b];
                        use.SetPixel(a, b, Color.FromArgb(255, tmp, tmp, tmp));
                    }


                if (success || success2)
                    success3 = true;
                else
                    success3 = false;
            }

            return (use);
        }
        /// <summary>
        /// Applys Sobel Operator to the Grey Scale Image
        /// </summary>
        /// <param name="use">Takes Grey Scale Image as Input</param>
        /// <returns>Return Grey Scale Image after applying Sobel Operator </returns>
        public static Bitmap Sobel(Bitmap use)
        {
            int Rows = use.Height;
            int Cols = use.Width;
            int r, c;
            int pixel;
            Bitmap sobel = new Bitmap(Rows, Cols);
            Bitmap gx = new Bitmap(Rows, Cols);
            Bitmap gy = new Bitmap(Rows, Cols);

            pixel = 0;
            for (r = 1; r < Rows - 1; r++)
                for (c = 1; c < Cols - 1; c++)
                {

                    int[] z = new Int32[10];
                    z[1] = Convert.ToInt32(use.GetPixel(r - 1, c - 1).R);
                    z[3] = Convert.ToInt32(use.GetPixel(r - 1, c + 1).R);
                    z[4] = Convert.ToInt32(use.GetPixel(r, c - 1).R);
                    z[6] = Convert.ToInt32(use.GetPixel(r, c + 1).R);
                    z[7] = Convert.ToInt32(use.GetPixel(r + 1, c - 1).R);
                    z[9] = Convert.ToInt32(use.GetPixel(r + 1, c + 1).R);
                    /* Apply Sobel operator. */
                    pixel = z[3] - z[1] + (2 * z[6]) - (2 * z[4]) + z[9] - z[7];

                    /* Normalize and take absolute value */
                    pixel = Math.Abs(pixel);

                    /* Check magnitude */
                    if (pixel < 255)
                        gy.SetPixel(r, c, Color.FromArgb(255, pixel, pixel, pixel));
                }

            pixel = 0;
            for (r = 1; r < Rows - 1; r++)
                for (c = 1; c < Cols - 1; c++)
                {
                    int[] z = new Int32[10];

                    z[1] = Convert.ToInt32(use.GetPixel(r - 1, c - 1).R);
                    z[3] = Convert.ToInt32(use.GetPixel(r - 1, c + 1).R);
                    z[2] = Convert.ToInt32(use.GetPixel(r - 1, c).R);
                    z[8] = Convert.ToInt32(use.GetPixel(r + 1, c).R);
                    z[7] = Convert.ToInt32(use.GetPixel(r + 1, c - 1).R);
                    z[9] = Convert.ToInt32(use.GetPixel(r + 1, c + 1).R);
                    /* Apply Sobel operator. */
                    pixel = z[7] - z[1] + (2 * z[8]) - (2 * z[2]) + z[9] - z[3];

                    /* Normalize and take absolute value */
                    pixel = Math.Abs(pixel);

                    /* Check magnitude */
                    if (pixel < 255)
                        gx.SetPixel(r, c, Color.FromArgb(255, pixel, pixel, pixel));
                }

            pixel = 0;
            for (r = 0; r < Rows; r++)
                for (c = 0; c < Cols; c++)
                {
                    Color x = gx.GetPixel(r, c);
                    Color y = gy.GetPixel(r, c);
                    pixel = Convert.ToInt32(x.R) + Convert.ToInt32(y.R);

                    if (pixel < 255)
                        sobel.SetPixel(r, c, Color.FromArgb(255, pixel, pixel, pixel));
                }
            return (sobel);
        }
    }
}